From 63b3f7114166dfe4070986b907f0ff3fa3cac430 Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Tue, 23 Oct 2018 22:12:19 +0200 Subject: [PATCH] Migration to Django 1.10 --- .gitignore | 1 + k4ever/api2/decorators.py | 2 +- k4ever/api2/handlers.py | 14 ++--- k4ever/api2/urls.py | 4 +- k4ever/buyable/admin.py | 1 + k4ever/buyable/management.py | 4 +- k4ever/buyable/models.py | 10 +-- .../templates/buyables/product_list.html | 12 ++-- k4ever/buyable/urls.py | 18 +++--- k4ever/buyable/views.py | 10 +-- k4ever/k4ever/__init__.py | 0 k4ever/{ => k4ever}/settings.py.template | 0 k4ever/{ => k4ever}/settings_default.py | 63 ++++++++++++------- k4ever/{ => k4ever}/urls.py | 23 ++++--- k4ever/main/admin.py | 1 + k4ever/main/filters.py | 52 ++++++++------- k4ever/main/management.py | 4 +- k4ever/main/models.py | 4 +- k4ever/main/templates/500.html | 15 ++--- k4ever/main/templates/admin/base.html | 9 +-- k4ever/main/templates/base.html | 19 +++--- .../main/templates/main/navbar-content.html | 36 +++++------ k4ever/main/templates/main/product_list.html | 10 +-- k4ever/main/templatetags/navigation_extras.py | 7 ++- k4ever/main/urls.py | 24 ++++--- k4ever/main/views.py | 30 ++++----- k4ever/manage.py | 27 +++++--- k4ever/transaction/models.py | 12 ++-- k4ever/transaction/urls.py | 9 +-- k4ever/transaction/views.py | 6 +- k4ever/wsgi.py | 20 ++++++ 31 files changed, 258 insertions(+), 189 deletions(-) create mode 100644 k4ever/k4ever/__init__.py rename k4ever/{ => k4ever}/settings.py.template (100%) rename k4ever/{ => k4ever}/settings_default.py (73%) rename k4ever/{ => k4ever}/urls.py (54%) create mode 100644 k4ever/wsgi.py diff --git a/.gitignore b/.gitignore index 6e6f6be..c93e5a4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ k4ever/k4ever.db k4ever/media/img/ k4ever/settings.py +k4ever/k4ever/settings.py *.kdev4 .kdev4 *.kate-swp diff --git a/k4ever/api2/decorators.py b/k4ever/api2/decorators.py index 772ed5a..bfae723 100644 --- a/k4ever/api2/decorators.py +++ b/k4ever/api2/decorators.py @@ -10,7 +10,7 @@ from django.contrib.auth.models import User, Group from piston.utils import rc from main.models import Plugin, PluginPermission -from settings import PLUGIN_GROUP_ID +from k4ever.settings import PLUGIN_GROUP_ID def manglePluginPerms(apiFunc): """ Changes to a given user when the authenticated user is an plugin. diff --git a/k4ever/api2/handlers.py b/k4ever/api2/handlers.py index de5ac4b..2d0664a 100644 --- a/k4ever/api2/handlers.py +++ b/k4ever/api2/handlers.py @@ -8,8 +8,8 @@ from easy_thumbnails.files import get_thumbnailer from piston.handler import BaseHandler from piston.utils import rc -from k4ever.buyable.models import * -from k4ever.transaction.models import * +from buyable.models import * +from transaction.models import * from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.models import Group from django.core.exceptions import MultipleObjectsReturned @@ -116,7 +116,7 @@ class BuyableItemHandler(BaseHandler): p.save(saveOrder=False) order.save() - return {'success': True, 'balance': request.user.get_profile().balance} + return {'success': True, 'balance': request.user.userprofile_set.get().balance} def bulkBuy(self, request): """Buy a :class:`Buyable ` item. @@ -179,7 +179,7 @@ class BuyableItemHandler(BaseHandler): p.save(saveOrder=False) order.save() - return {'success': True, 'balance': request.user.get_profile().balance} + return {'success': True, 'balance': request.user.userprofile_set.get().balance} class BuyableTypeHandler(BaseHandler): @@ -290,7 +290,7 @@ class TransactionTransactHandler(BaseHandler): return getError(rc.BAD_REQUEST, "Your TransactionType could not be found") trans = Transaction(user=request.user, transactionType=tType, amount=amount, checked=not tType.needsCheck) trans.save() - return {'success': True, 'balance': request.user.get_profile().balance} + return {'success': True, 'balance': request.user.userprofile_set.get().balance} class TransactionTypeHandler(BaseHandler): """Handler for :class:`Transaction Types ` @@ -348,7 +348,7 @@ class TransactionVirtualHandler(BaseHandler): return getError(rc.BAD_REQUEST, "The recipient user does not exist.") trans = VirtualTransaction(user=request.user, recipient=recipient, amount=amount, comment=comment) trans.save() - return {'success': True, 'balance': request.user.get_profile().balance} + return {'success': True, 'balance': request.user.userprofile_set.get().balance} class AccountBalanceHandler(BaseHandler): """Handler for the user's account balance""" @@ -357,7 +357,7 @@ class AccountBalanceHandler(BaseHandler): @manglePluginPerms def read(self, request): """Returns the user's current account balance""" - balance = request.user.get_profile().balance + balance = request.user.userprofile_set.get().balance return {'balance': balance} class AuthBlobHandler(BaseHandler): diff --git a/k4ever/api2/urls.py b/k4ever/api2/urls.py index df4b8a5..b86faa6 100644 --- a/k4ever/api2/urls.py +++ b/k4ever/api2/urls.py @@ -5,7 +5,7 @@ # # Licensed under GNU Affero General Public License v3 or later -from django.conf.urls.defaults import * +from django.conf.urls import url, include from piston.resource import Resource from piston.authentication import HttpBasicAuthentication from api2.authentication import DjangoAuthentication, MultiAuthentication @@ -47,7 +47,7 @@ authUserRes = CsrfExemptResource(handler=AuthUserHandler, **ad) configRes = CsrfExemptResource(handler=ConfigHandler, **ad) -urlpatterns = patterns('', +urlpatterns = ( url(r'buyable/item/?$', buyableItemRes), url(r'buyable/item/(?P\d+)/?$', buyableItemRes), url(r'buyable/item/bulkbuy/?$', buyableItemRes, {'bulkBuy': True}), diff --git a/k4ever/buyable/admin.py b/k4ever/buyable/admin.py index 38a589c..92a8748 100644 --- a/k4ever/buyable/admin.py +++ b/k4ever/buyable/admin.py @@ -15,6 +15,7 @@ class BuyableAdminForm(forms.ModelForm): """ Special BuyableAdminForm which checks the buyable image for an 1:1 aspect ratio. """ class Meta: model = Buyable + exclude = [] def clean_image(self): img = self.cleaned_data['image'] diff --git a/k4ever/buyable/management.py b/k4ever/buyable/management.py index f555b50..2f62d2d 100644 --- a/k4ever/buyable/management.py +++ b/k4ever/buyable/management.py @@ -1,4 +1,4 @@ -from django.db.models.signals import post_syncdb +from django.db.models.signals import post_migrate from django.core.management import commands, call_command import buyable.models @@ -6,5 +6,5 @@ def createBuyableTypes(sender, app, created_models, **kwargs): if buyable.models.BuyableType in created_models: call_command("loaddata", "buyable_types") -post_syncdb.connect(createBuyableTypes, sender=buyable.models) +post_migrate.connect(createBuyableTypes, sender=buyable.models) diff --git a/k4ever/buyable/models.py b/k4ever/buyable/models.py index fe83b28..427ed8c 100644 --- a/k4ever/buyable/models.py +++ b/k4ever/buyable/models.py @@ -79,7 +79,7 @@ class Order(models.Model): return l.rstrip(u", ") def save(self, *args, **kwargs): - profile = self.user.get_profile() + profile = self.user.userprofile_set.get() if self.id == None: # new item, get it! profile.balance -= self.price @@ -88,12 +88,12 @@ class Order(models.Model): # get old oldobj = Order.objects.get(id=self.id) if oldobj.user == self.user: - profile = self.user.get_profile() + profile = self.user.userprofile_set.get() profile.balance -= (self.price - oldobj.price) profile.save() else: - oldProfile = oldobj.user.get_profile() - newProfile = self.user.get_profile() + oldProfile = oldobj.user.userprofile_set.get() + newProfile = self.user.userprofile_set.get() oldProfile.balance += oldobj.price oldProfile.save() newprofile.balance -= self.price @@ -111,7 +111,7 @@ class Order(models.Model): # where all the buyables have not updated the price updOrder = Order.objects.get(id=instance.id) if updOrder.price != Decimal("0"): - profile = updOrder.user.get_profile() + profile = updOrder.user.userprofile_set.get() profile.balance += updOrder.price profile.save() diff --git a/k4ever/buyable/templates/buyables/product_list.html b/k4ever/buyable/templates/buyables/product_list.html index cd905b4..6deea08 100644 --- a/k4ever/buyable/templates/buyables/product_list.html +++ b/k4ever/buyable/templates/buyables/product_list.html @@ -15,21 +15,21 @@ {% for buyable in buyables %}
  • - + {{ buyable.name }}
    -

    {{ buyable.name }}

    +

    {{ buyable.name }}

    diff --git a/k4ever/buyable/urls.py b/k4ever/buyable/urls.py index 2bbce70..00e15e7 100644 --- a/k4ever/buyable/urls.py +++ b/k4ever/buyable/urls.py @@ -5,14 +5,16 @@ # # Licensed under GNU Affero General Public License v3 or later -from django.conf.urls.defaults import * +from django.conf.urls import url + +import buyable.views #/store/ -urlpatterns = patterns('', - (r'^$', 'buyable.views.showItems'), - url(r'^show/(\d+)/$', 'buyable.views.showItem', name='buyable_show'), - url(r'^buy/(\d+)/$', 'buyable.views.buyItem', name='buyable_buy'), - url(r'^buy/(\d+)/(with/deposit|only/deposit)/$', 'buyable.views.buyItem', name='buyable_buy'), - (r'^bought/(\d+)/?$', 'buyable.views.boughtItem'), - (r'^history/?$', 'buyable.views.history'), +urlpatterns = ( + url(r'^$', buyable.views.showItems, name='buyable_overview'), + url(r'^show/(\d+)/$', buyable.views.showItem, name='buyable_show'), + url(r'^buy/(\d+)/$', buyable.views.buyItem, name='buyable_buy'), + url(r'^buy/(\d+)/(with/deposit|only/deposit)/$', buyable.views.buyItem, name='buyable_buy'), + url(r'^bought/(\d+)/?$', buyable.views.boughtItem), + url(r'^history/?$', buyable.views.history, name='buyable_history'), ) diff --git a/k4ever/buyable/views.py b/k4ever/buyable/views.py index 6b7ff8c..f025fed 100644 --- a/k4ever/buyable/views.py +++ b/k4ever/buyable/views.py @@ -6,7 +6,7 @@ # # Licensed under GNU Affero General Public License v3 or later -from django.shortcuts import render_to_response +from django.shortcuts import render from django.template import RequestContext from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect @@ -29,7 +29,7 @@ def showItems(request): if order_by == 'price': items = items.order_by('price') - return render_to_response("buyables/showItems.html", {'items': items}, RequestContext(request)) + return render(request, "buyables/showItems.html", {'items': items}) @login_required def showItem(request, itemid): @@ -38,7 +38,7 @@ def showItem(request, itemid): except Buyable.DoesNotExist: # baww, kein item mit der id :( (oder mutax trollt rum) return HttpResponseRedirect("/buy/") - return render_to_response("buyables/showItem.html", {'item': item}, RequestContext(request)) + return render(request, "buyables/showItem.html", {'item': item}) @login_required @@ -76,7 +76,7 @@ def boughtItem(request, orderid): if error == None and (item.user != request.user): item1 = None error = u"Diese Items gehören dir nicht" - return render_to_response("buyables/itemBought.html", {'order': item, 'error': error}, RequestContext(request)) + return render(request, "buyables/itemBought.html", {'order': item, 'error': error}) @login_required def history(request): @@ -98,4 +98,4 @@ def history(request): # If page is out of range, deliver last page histpage = paginator.page(paginator.num_pages) - return render_to_response("buyables/history.html", {'history': histpage}, RequestContext(request)) + return render(request, "buyables/history.html", {'history': histpage}) diff --git a/k4ever/k4ever/__init__.py b/k4ever/k4ever/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/k4ever/settings.py.template b/k4ever/k4ever/settings.py.template similarity index 100% rename from k4ever/settings.py.template rename to k4ever/k4ever/settings.py.template diff --git a/k4ever/settings_default.py b/k4ever/k4ever/settings_default.py similarity index 73% rename from k4ever/settings_default.py rename to k4ever/k4ever/settings_default.py index ca91bfb..89db7a0 100644 --- a/k4ever/settings_default.py +++ b/k4ever/k4ever/settings_default.py @@ -1,7 +1,10 @@ # Django settings for k4ever project. +import os +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + DEBUG = False -TEMPLATE_DEBUG = DEBUG PISTON_DISPLAY_ERRORS = DEBUG DEBUG_PROPOGATE_EXCEPTIONS = DEBUG @@ -14,7 +17,7 @@ MANAGERS = ADMINS # use sqlite by default DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'k4ever.db', # Or path to database file if using sqlite3. 'USER': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. @@ -59,6 +62,7 @@ MEDIA_ROOT = 'media/' # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" MEDIA_URL = '/media/' +STATIC_URL = '/static/' # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. @@ -77,16 +81,36 @@ AUTH_PROFILE_MODULE = 'main.UserProfile' LOGIN_URL = '/user/login/' LOGIN_REDIRECT_URL = '/' +ALLOWED_HOSTS = ['*'] + AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', ) -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'django.template.loaders.app_directories.load_template_source', -) + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, "templates/")], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +#TEMPLATE_CONTEXT_PROCESSORS = ( +# "django.contrib.auth.context_processors.auth", +# "django.core.context_processors.debug", +# "django.core.context_processors.i18n", +# "django.core.context_processors.media", +# "django.core.context_processors.static", +#) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', @@ -98,31 +122,24 @@ MIDDLEWARE_CLASSES = ( ROOT_URLCONF = 'k4ever.urls' -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', + 'django.contrib.staticfiles', 'buyable', 'transaction', 'main', 'django.contrib.admin', 'easy_thumbnails', + 'piston', ) -TEMPLATE_CONTEXT_PROCESSORS = ( - "django.contrib.auth.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "django.core.context_processors.static", - "django.contrib.messages.context_processors.messages", - "django.core.context_processors.request", -) \ No newline at end of file + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "media"), +] +STATIC_ROOT = os.path.join(BASE_DIR, "static") + diff --git a/k4ever/urls.py b/k4ever/k4ever/urls.py similarity index 54% rename from k4ever/urls.py rename to k4ever/k4ever/urls.py index bd0e7e7..9771e3d 100644 --- a/k4ever/urls.py +++ b/k4ever/k4ever/urls.py @@ -5,11 +5,14 @@ # # Licensed under GNU Affero General Public License v3 or later -from django.conf.urls.defaults import * +from django.conf.urls import url, include from django.contrib import admin admin.autodiscover() +import django.views.static -urlpatterns = patterns('', +import main.views + +urlpatterns = ( # Example: # (r'^k4ever/', include('k4ever.foo.urls')), @@ -17,15 +20,15 @@ urlpatterns = patterns('', # to INSTALLED_APPS to enable admin documentation: # (r'^admin/doc/', include('django.contrib.admindocs.urls')), # user stuff? go to main - (r'^$', 'main.views.startpage'), - (r'^api2/', include('api2.urls')), - (r'^user/', include('main.urls')), - (r'^transaction/', include('transaction.urls')), - (r'^store/', include('buyable.urls')), - (r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': 'media'}), - (r'^docs/(?P.*)$', 'django.views.static.serve', {'document_root': 'docs'}), + url(r'^$', main.views.startpage, name='main.views.startpage'), + url(r'^api2/', include('api2.urls')), + url(r'^user/', include('main.urls')), + url(r'^transaction/', include('transaction.urls')), + url(r'^store/', include('buyable.urls')), + url(r'^media/(?P.*)$', django.views.static.serve, {'document_root': 'media'}), + url(r'^docs/(?P.*)$', django.views.static.serve, {'document_root': 'docs'}), # Uncomment the next line to enable the admin: - (r'^admin/', include(admin.site.urls)), + url(r'^admin/', include(admin.site.urls)), ) diff --git a/k4ever/main/admin.py b/k4ever/main/admin.py index 6500df0..1c5cb2b 100644 --- a/k4ever/main/admin.py +++ b/k4ever/main/admin.py @@ -15,6 +15,7 @@ class PluginAdminForm(forms.ModelForm): """ Form made to require that the user of a plugin is in the plugin group """ class Meta: model = Plugin + exclude = [] def clean_user(self): user = self.cleaned_data['user'] diff --git a/k4ever/main/filters.py b/k4ever/main/filters.py index e827cb8..e96fe1a 100644 --- a/k4ever/main/filters.py +++ b/k4ever/main/filters.py @@ -5,28 +5,32 @@ # # Licensed under GNU Affero General Public License v3 or later -from django.contrib.admin.filterspecs import FilterSpec, BooleanFieldFilterSpec +# FIXME: this needs to be reimplemented (not compatible with django 1.10+) +# https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter +# http://stackoverflow.com/a/10644089 -class IsNegativeFilterSpec(FilterSpec): - """ Custom filter to display only users with negative balance """ - def __init__(self, f, request, *args, **kwargs): - super(IsNegativeFilterSpec, self).__init__(f, request, *args, **kwargs) - self.lookup_kwarg = '%s__lt' % f.name - self.lookup_val = request.GET.get(self.lookup_kwarg, None) # Check if current request already has a filter - - def title(self): - return 'Kontostand' - - def choices(self, cl): - yield { - 'selected': self.lookup_val == None, - 'query_string': "?", - 'display': 'Alle'} - yield { - 'selected': self.lookup_val == '0', - 'query_string': cl.get_query_string( - {self.lookup_kwarg: 0}, - ['balance__isnull']), - 'display': 'Nur Negative'} - -FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'has_negative_filter', False), IsNegativeFilterSpec)) +#from django.contrib.admin.filterspecs import FilterSpec, BooleanFieldFilterSpec +# +#class IsNegativeFilterSpec(FilterSpec): +# """ Custom filter to display only users with negative balance """ +# def __init__(self, f, request, *args, **kwargs): +# super(IsNegativeFilterSpec, self).__init__(f, request, *args, **kwargs) +# self.lookup_kwarg = '%s__lt' % f.name +# self.lookup_val = request.GET.get(self.lookup_kwarg, None) # Check if current request already has a filter +# +# def title(self): +# return 'Kontostand' +# +# def choices(self, cl): +# yield { +# 'selected': self.lookup_val == None, +# 'query_string': "?", +# 'display': 'Alle'} +# yield { +# 'selected': self.lookup_val == '0', +# 'query_string': cl.get_query_string( +# {self.lookup_kwarg: 0}, +# ['balance__isnull']), +# 'display': 'Nur Negative'} +# +#FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'has_negative_filter', False), IsNegativeFilterSpec)) diff --git a/k4ever/main/management.py b/k4ever/main/management.py index cbfe67d..ca9c166 100644 --- a/k4ever/main/management.py +++ b/k4ever/main/management.py @@ -1,4 +1,4 @@ -from django.db.models.signals import post_syncdb +from django.db.models.signals import post_migrate from django.core.management import commands, call_command import django.contrib.auth @@ -6,5 +6,5 @@ def createPluginGroup(sender, app, created_models, **kwargs): if django.contrib.auth.models.Group in created_models: call_command("loaddata", "group_plugin") -post_syncdb.connect(createPluginGroup, sender=django.contrib.auth.models) +post_migrate.connect(createPluginGroup, sender=django.contrib.auth.models) diff --git a/k4ever/main/models.py b/k4ever/main/models.py index 0417405..210685e 100644 --- a/k4ever/main/models.py +++ b/k4ever/main/models.py @@ -12,7 +12,7 @@ from decimal import Decimal class UserProfile(models.Model): """ Contains data for a user, especially the account balance. """ - user = models.ForeignKey(User, unique=True) + user = models.OneToOneField(User) balance = models.DecimalField(max_digits=9, decimal_places=2, default=Decimal(0)) balance.has_negative_filter = True @@ -45,7 +45,7 @@ class Plugin(models.Model): The other attributes are used for plugin/user read/write access to the authblob. """ - user = models.ForeignKey(User, unique=True) + user = models.OneToOneField(User) # plugin info name = models.CharField(max_length=40) diff --git a/k4ever/main/templates/500.html b/k4ever/main/templates/500.html index f9eb85b..a5eb6de 100644 --- a/k4ever/main/templates/500.html +++ b/k4ever/main/templates/500.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load static %} {% comment %} # This file is part of k4ever, a point-of-sale system @@ -11,16 +12,16 @@ {% block head %} + href="{% static "css/style.css" %}" /> {% block extrastyle %}{% endblock %} - - - - - + + + + + {% endblock head %} {% block "content" %} diff --git a/k4ever/main/templates/admin/base.html b/k4ever/main/templates/admin/base.html index 3d7ffb1..f8cfa5d 100644 --- a/k4ever/main/templates/admin/base.html +++ b/k4ever/main/templates/admin/base.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load static %} {% comment %} # This file is part of k4ever, a point-of-sale system @@ -12,13 +13,13 @@ {# load url from future #} {% block extrastyle %} - - - {% if LANGUAGE_BIDI %}{% endif %} + + + {% if LANGUAGE_BIDI %}{% endif %} {% endblock %} {% block extrahead %} - + {% block blockbots %}{% endblock %} {% endblock %} diff --git a/k4ever/main/templates/base.html b/k4ever/main/templates/base.html index cf670fe..dba27fb 100644 --- a/k4ever/main/templates/base.html +++ b/k4ever/main/templates/base.html @@ -6,6 +6,7 @@ # # Licensed under GNU Affero General Public License v3 or later {% endcomment %} +{% load static %} @@ -13,20 +14,20 @@ {% block head %} + href="{% static "css/style.css" %}" /> {% block extrastyle %}{% endblock %} - - - - - - + + + + + + {% block extrahead %}{% endblock %} {% endblock head %} - Freitagsrundenkasse{% block "title" %}{% endblock %} + Unbranded K4Ever{% block "title" %}{% endblock %}