From aa20dc8534207e68e3bca1f742d00761372e6a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?moritz=20m=C3=BCnch?= Date: Sun, 20 Dec 2020 01:17:10 +0100 Subject: [PATCH 1/5] #13 add etag header with last_modified function to country view --- coinmanager/coinc/models.py | 6 +++++- coinmanager/coinc/views.py | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/coinmanager/coinc/models.py b/coinmanager/coinc/models.py index 0fb7a6f..fd7bfeb 100644 --- a/coinmanager/coinc/models.py +++ b/coinmanager/coinc/models.py @@ -20,7 +20,7 @@ from datetime import datetime, date -from django.db.models import BooleanField, CASCADE, CharField, DateField, ForeignKey, Model, PositiveIntegerField, PositiveSmallIntegerField, TextField +from django.db.models import BooleanField, CASCADE, CharField, DateField, DateTimeField, ForeignKey, Model, PositiveIntegerField, PositiveSmallIntegerField, TextField year_now = int(datetime.now().year) @@ -85,6 +85,10 @@ class Coin(Model): found_on = DateField('Eingetragen am', default=date.today) + date_added = DateTimeField('Hinzugefügt', auto_now_add=True) + + date_modified = DateTimeField('Geändert', auto_now=True) + circulation = PositiveIntegerField('Auflage', default=0) buy_only = BooleanField('Kursmünze', default=False) diff --git a/coinmanager/coinc/views.py b/coinmanager/coinc/views.py index ce70abe..1311076 100644 --- a/coinmanager/coinc/views.py +++ b/coinmanager/coinc/views.py @@ -24,6 +24,7 @@ from django.conf import settings from django.http import HttpResponse, Http404 from django.template import loader from django.template.defaultfilters import register +from django.views.decorators.http import condition from .models import Country, Stamp, Coin, User @@ -46,8 +47,16 @@ def coin_sum_of_(country): coin_count['total'] += 200 * coin_count[value] else: coin_count['total'] += value * coin_count[value] - coin_count['total'] /= 100 - return coin_count['total'] + + return coin_count['total'] / 100 + + +def latest_coin_added_to_(request, name_iso): + ''' return the datetime of the last coin added to a country + >>> latest_coin_added_to_(germany) + datetime.datetime + ''' + return Coin.objects.filter(country=name_iso).latest('date_modified').date_modified def index(request): @@ -66,6 +75,7 @@ def index(request): return HttpResponse(template.render(context, request)) +@condition(last_modified_func=latest_coin_added_to_) def detail_country(request, name_iso): ''' wrapper_view for a *single* country ''' From 2ca47411ef22d7b7a941cde71346ddcd4ae89d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?moritz=20m=C3=BCnch?= Date: Sun, 20 Dec 2020 01:44:05 +0100 Subject: [PATCH 2/5] formatting --- coinmanager/coinc/views.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/coinmanager/coinc/views.py b/coinmanager/coinc/views.py index 1311076..52d28e2 100644 --- a/coinmanager/coinc/views.py +++ b/coinmanager/coinc/views.py @@ -24,25 +24,39 @@ from django.conf import settings from django.http import HttpResponse, Http404 from django.template import loader from django.template.defaultfilters import register +from django.views.decorators.cache import cache_page from django.views.decorators.http import condition from .models import Country, Stamp, Coin, User def total_coin_sum(): + ''' add each coin_sum from each country and return the result + >>> total_coin_sum() + 173.57 + ''' + total_coin_sum = 0 for country in Country.objects.order_by('name'): total_coin_sum += coin_sum_of_(country) + return total_coin_sum def coin_sum_of_(country): + ''' calculate the sum of all coins from a country + >>> coin_sum_of_(germany) + 346.82 + ''' + coin_count = {'total': 0} for value in [1, 2, 5, 10, 20, 50, 100, 200, 201, 202, 203]: + coin_count[value] = Coin.objects.filter( - country=country, - value=value - ).exclude(found_by__isnull=True).count() + country=country, + value=value + ).exclude(found_by__isnull=True).count() + if value > 200: coin_count['total'] += 200 * coin_count[value] else: From 8ee6ae9016d7771f82609d5417e3477a52239a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?moritz=20m=C3=BCnch?= Date: Sun, 20 Dec 2020 14:33:54 +0100 Subject: [PATCH 3/5] #13 update global cache backend, add last_modified complete, add etag for documentation reasons, will be removed in next commit --- coinmanager/coinc/views.py | 59 +++++++---------------------- coinmanager/coinmanager/settings.py | 18 +++++++-- 2 files changed, 29 insertions(+), 48 deletions(-) diff --git a/coinmanager/coinc/views.py b/coinmanager/coinc/views.py index 52d28e2..1824f43 100644 --- a/coinmanager/coinc/views.py +++ b/coinmanager/coinc/views.py @@ -27,52 +27,15 @@ from django.template.defaultfilters import register from django.views.decorators.cache import cache_page from django.views.decorators.http import condition +from .cache import (get_etag_index, set_etag_index, + get_etag_country, set_etag_country, + get_last_modified_index, set_last_modified_index, + get_last_modified_country, set_last_modified_country) from .models import Country, Stamp, Coin, User +from .helper import total_coin_sum, coin_sum_of_ -def total_coin_sum(): - ''' add each coin_sum from each country and return the result - >>> total_coin_sum() - 173.57 - ''' - - total_coin_sum = 0 - for country in Country.objects.order_by('name'): - total_coin_sum += coin_sum_of_(country) - - return total_coin_sum - - -def coin_sum_of_(country): - ''' calculate the sum of all coins from a country - >>> coin_sum_of_(germany) - 346.82 - ''' - - coin_count = {'total': 0} - for value in [1, 2, 5, 10, 20, 50, 100, 200, 201, 202, 203]: - - coin_count[value] = Coin.objects.filter( - country=country, - value=value - ).exclude(found_by__isnull=True).count() - - if value > 200: - coin_count['total'] += 200 * coin_count[value] - else: - coin_count['total'] += value * coin_count[value] - - return coin_count['total'] / 100 - - -def latest_coin_added_to_(request, name_iso): - ''' return the datetime of the last coin added to a country - >>> latest_coin_added_to_(germany) - datetime.datetime - ''' - return Coin.objects.filter(country=name_iso).latest('date_modified').date_modified - - +@condition(etag_func=get_etag_index, last_modified_func=get_last_modified_index) def index(request): ''' index view ''' @@ -83,13 +46,13 @@ def index(request): context = { 'countrys': countrys, 'users': users, - 'coin_sum': f"{coin_sum:.2f} €" + 'coin_sum': f'{coin_sum:.2f} €' } return HttpResponse(template.render(context, request)) -@condition(last_modified_func=latest_coin_added_to_) +@condition(etag_func=get_etag_country, last_modified_func=get_last_modified_country) def detail_country(request, name_iso): ''' wrapper_view for a *single* country ''' @@ -292,6 +255,8 @@ def add_coin(request): name no - str found_by no None obj User found_on no None str %Y-%m-%d + date-added no auto str %Y-%m-%d %H:%M:%S.%s + date-modified no auto str %Y-%m-%d %H:%M:%S.%s circulation no 0 int [0; 1000000000] buy_only no False bool checked no False bool @@ -409,6 +374,10 @@ def add_coin(request): in_collector = ec, exists = exists) + set_etag_index() + set_last_modified_index() + set_etag_country(name_iso) + set_last_modified_country(name_iso) return response() diff --git a/coinmanager/coinmanager/settings.py b/coinmanager/coinmanager/settings.py index 2b5ddae..7181936 100644 --- a/coinmanager/coinmanager/settings.py +++ b/coinmanager/coinmanager/settings.py @@ -129,6 +129,18 @@ MAINTENANCE_MODE_READ_ONLY = False # do not redirect after login LOGIN_REDIRECT_URL = './' -# caching -CACHE_MIDDLEWARE_ALIAS = willipink_coinc -CACHE_MIDDLEWARE_SECONDS = 600 +# caching modes, i.e. file based, memcached, or other fancy stuff +# https://docs.djangoproject.com/en/3.1/topics/cache/#cache-arguments +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', + 'LOCATION': '/var/tmp/django_cache', + 'TIMEOUT': None, + } +} + +# per-site cache +# updatecachemiddleware: adds 'Expires' and 'Cache-Control' headers to give the +# page a maximum age CACHE_MIDDLEWARE_SECONDS +# CACHE_MIDDLEWARE_ALIAS = 'default' +# CACHE_MIDDLEWARE_SECONDS = 600 From 9d3c24643632ace89ba2531041e62862c50f7c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?moritz=20m=C3=BCnch?= Date: Sun, 20 Dec 2020 14:34:39 +0100 Subject: [PATCH 4/5] #13 this one was missing still for cache stuff --- coinmanager/coinc/cache.py | 85 +++++++++++++++++++++++++++++++++++++ coinmanager/coinc/helper.py | 54 +++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 coinmanager/coinc/cache.py create mode 100644 coinmanager/coinc/helper.py diff --git a/coinmanager/coinc/cache.py b/coinmanager/coinc/cache.py new file mode 100644 index 0000000..92eeabd --- /dev/null +++ b/coinmanager/coinc/cache.py @@ -0,0 +1,85 @@ +# encoding: utf-8 +# +# Copyright (C) 2020 willipink.eu +# Author Moritz Münch moritzmuench@mailbox.org +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + + +from hashlib import sha256 +from random import random + +from django.core.cache import cache +from django.http import Http404 + +#todo we dont need this, no db queries +from .models import Coin +from .models import Country + + +def get_etag_index(request): + return cache.get(f'etag_index', set_etag_index()) + + +def get_last_modified_index(request): + return cache.get(f'last_modified_index', set_last_modified_index()) + + +def set_last_modified_index(): + ''' set and return the datetime of the last coin added ''' + try: + last_modified = Coin.objects.latest('date_modified').date_modified + except Coin.DoesNotExist: + raise Http404(f'Das Land "{name_iso}" existiert nicht') + cache.set(f'last_modified_index', last_modified) + return last_modified + +def get_last_modified_country(request, name_iso): + return cache.get(f'last_modified_{name_iso}', set_last_modified_country(name_iso)) + + +def set_last_modified_country(name_iso): + ''' return the datetime of the last coin added to a country ''' + try: + last_modified = Coin.objects.filter(country=name_iso).latest('date_modified').date_modified + except Coin.DoesNotExist: + raise Http404(f'Das Land "{name_iso}" existiert nicht') + cache.set(f'last_modified_{name_iso}', last_modified) + return last_modified + + +def set_etag_index(): + etag = '' + for country in Country.objects.order_by('name_iso'): + etag += get_etag_country_(country.name_iso) + etag = sha256(etag.encode('utf-8')).hexdigest()[0:9] + cache.set(f'etag_index', etag) + return etag + + +def get_etag_country_(name_iso): + return cache.get(f'etag_{name_iso}', set_etag_country(name_iso)) + + +def get_etag_country(request, name_iso): + return get_etag_country_(name_iso) + + +def set_etag_country(name_iso): + print(name_iso, end='') + print(cache.get(f'etag_{name_iso}', f'error {name_iso}')) + etag = sha256(str(random()).encode('utf-8')).hexdigest()[0:9] + cache.set(f'etag_{name_iso}', etag) + return etag diff --git a/coinmanager/coinc/helper.py b/coinmanager/coinc/helper.py new file mode 100644 index 0000000..0d7aca4 --- /dev/null +++ b/coinmanager/coinc/helper.py @@ -0,0 +1,54 @@ +# encoding: utf-8 +# +# Copyright (C) 2020 willipink.eu +# Author Moritz Münch moritzmuench@mailbox.org +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from .models import Country, Coin + +def total_coin_sum(): + ''' add each coin_sum from each country and return the result + >>> total_coin_sum() + 173.57 + ''' + + total_coin_sum = 0 + for country in Country.objects.order_by('name'): + total_coin_sum += coin_sum_of_(country) + + return total_coin_sum + + +def coin_sum_of_(country): + ''' calculate the sum of all coins from a country + >>> coin_sum_of_(germany) + 346.82 + ''' + + coin_count = {'total': 0} + for value in [1, 2, 5, 10, 20, 50, 100, 200, 201, 202, 203]: + + coin_count[value] = Coin.objects.filter( + country=country, + value=value + ).exclude(found_by__isnull=True).count() + + if value > 200: + coin_count['total'] += 200 * coin_count[value] + else: + coin_count['total'] += value * coin_count[value] + + return coin_count['total'] / 100 From d9bfb40bfcc5035aeb5ae264fb1b94f3e75bed76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?moritz=20m=C3=BCnch?= Date: Sat, 29 May 2021 09:53:42 +0200 Subject: [PATCH 5/5] #13 intermediate --- coinmanager/coinc/cache.py | 32 +------------------ .../coinc/templates/coinc/controlbar.html | 7 ++-- coinmanager/coinc/templates/header.html | 3 ++ coinmanager/coinc/views.py | 16 ++++------ coinmanager/coinmanager/settings.py | 5 +-- 5 files changed, 18 insertions(+), 45 deletions(-) diff --git a/coinmanager/coinc/cache.py b/coinmanager/coinc/cache.py index 92eeabd..79a5ef0 100644 --- a/coinmanager/coinc/cache.py +++ b/coinmanager/coinc/cache.py @@ -24,13 +24,7 @@ from random import random from django.core.cache import cache from django.http import Http404 -#todo we dont need this, no db queries from .models import Coin -from .models import Country - - -def get_etag_index(request): - return cache.get(f'etag_index', set_etag_index()) def get_last_modified_index(request): @@ -46,6 +40,7 @@ def set_last_modified_index(): cache.set(f'last_modified_index', last_modified) return last_modified + def get_last_modified_country(request, name_iso): return cache.get(f'last_modified_{name_iso}', set_last_modified_country(name_iso)) @@ -58,28 +53,3 @@ def set_last_modified_country(name_iso): raise Http404(f'Das Land "{name_iso}" existiert nicht') cache.set(f'last_modified_{name_iso}', last_modified) return last_modified - - -def set_etag_index(): - etag = '' - for country in Country.objects.order_by('name_iso'): - etag += get_etag_country_(country.name_iso) - etag = sha256(etag.encode('utf-8')).hexdigest()[0:9] - cache.set(f'etag_index', etag) - return etag - - -def get_etag_country_(name_iso): - return cache.get(f'etag_{name_iso}', set_etag_country(name_iso)) - - -def get_etag_country(request, name_iso): - return get_etag_country_(name_iso) - - -def set_etag_country(name_iso): - print(name_iso, end='') - print(cache.get(f'etag_{name_iso}', f'error {name_iso}')) - etag = sha256(str(random()).encode('utf-8')).hexdigest()[0:9] - cache.set(f'etag_{name_iso}', etag) - return etag diff --git a/coinmanager/coinc/templates/coinc/controlbar.html b/coinmanager/coinc/templates/coinc/controlbar.html index 0dd940f..d46291e 100644 --- a/coinmanager/coinc/templates/coinc/controlbar.html +++ b/coinmanager/coinc/templates/coinc/controlbar.html @@ -1,9 +1,11 @@ +{% load cache %} +{% csrf_token %} +{% cache None controlbar user %}
- {% csrf_token %} {% if user.is_authenticated %} @@ -14,7 +16,6 @@
- +{% endcache %} {% if not user.is_authenticated %}