Merge branch 'master' of ssh://willipink.eu:3456/moritz/coinmanager

This commit is contained in:
willipink 2021-05-29 07:56:23 +00:00
commit 5ee77597ba
7 changed files with 153 additions and 32 deletions

View File

@ -0,0 +1,55 @@
# 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 <http://www.gnu.org/licenses/>.
from hashlib import sha256
from random import random
from django.core.cache import cache
from django.http import Http404
from .models import Coin
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

View File

@ -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 <http://www.gnu.org/licenses/>.
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

View File

@ -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)

View File

@ -1,9 +1,11 @@
{% load cache %}
{% csrf_token %}
{% cache None controlbar user %}
<style type="text/css">{% for user in users %}
div.{{ user.name }} { background-color: {{ user.color }} !important; }{% endfor %}
</style>
<div id="button_control">
{% csrf_token %}
{% if user.is_authenticated %}
<button id="begin_edit" class="btn btn-info" title="Hinzufügen"><i class="fas fa-plus"></i><span> Hinzufügen</span></button>
<button id="do_logout" class="btn btn-info" title="Abmelden"><i class="fas fa-sign-out-alt"></i></button>
@ -14,7 +16,6 @@
<!-- navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
{% csrf_token %}
<!-- advanced options -->
<div id="advanced_options">
@ -114,7 +115,7 @@
</div>
</div>
</div>
{% endcache %}
<!-- modal login -->
{% if not user.is_authenticated %}
<div id="login" class="modal-container">

View File

@ -1,3 +1,5 @@
{% load cache %}
{% cache None header %}
<!DOCTYPE html>
<!--
@ -53,3 +55,4 @@
<title>{{ title }}</title>
</head>
<body>
{% endcache %}

View File

@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime, date
from json import dumps
@ -24,32 +25,15 @@ 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 .cache import (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():
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):
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]
coin_count['total'] /= 100
return coin_count['total']
@condition(last_modified_func=get_last_modified_index)
def index(request):
''' index view '''
@ -60,12 +44,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=get_last_modified_country)
def detail_country(request, name_iso):
''' wrapper_view for a *single* country '''
@ -194,6 +179,7 @@ def show_country(country, single_country=False):
c['years'][str(coin.year)][stamp][coin.value] = {
'marker': marker,
'name': name,
'date_modified': coin.date_modified,
'td_class': td_class,
'div_class': div_class,
'special_class': special_class,
@ -225,6 +211,7 @@ def show_coin(coin, value):
'value': value,
'marker': coin['marker'],
'name': coin['name'],
'date_modified': coin['date_modified'],
'td_class': coin['td_class'],
'div_class': coin['div_class'],
'special_class': coin['special_class'],
@ -268,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
@ -385,6 +374,8 @@ def add_coin(request):
in_collector = ec,
exists = exists)
set_last_modified_index()
set_last_modified_country(country.name_iso)
return response()

View File

@ -44,10 +44,11 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
# 'django.middleware.cache.UpdateCacheMiddleware', # per-site cache
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware', # per-site cache
'django.middleware.csrf.CsrfViewMiddleware',
# 'django.middleware.http.ConditionalGetMiddleware', # set 'ETag' and 'Last Modified' headers
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
@ -129,6 +130,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