diff --git a/Vagrantfile b/Vagrantfile index 1ee8bbe..228ef83 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -30,7 +30,8 @@ Vagrant.configure("2") do |config| #zu installierende Pakete apt-get install -y apache2 python3-django mariadb-server avahi-daemon \ libnss-mdns libapache2-mod-wsgi-py3 python3-mysqldb python3-pip - pip3 install django-extensions Pillow django-bootstrap3 + pip3 install django-extensions Pillow pyaml django-bootstrap3 + /vagrant/ansible/roles/web_AI-5/tasks/setup_script.sh SHELL diff --git a/ansible/roles/web_AI-5/tasks/main.yml b/ansible/roles/web_AI-5/tasks/main.yml index 2e067d1..93216d1 100644 --- a/ansible/roles/web_AI-5/tasks/main.yml +++ b/ansible/roles/web_AI-5/tasks/main.yml @@ -15,6 +15,7 @@ git: repo=https://git.2li.ch/ibz/web_AI-5.git dest="/vagrant" force=yes + version=production - name: Set Permissions on the repository file: @@ -27,6 +28,7 @@ name: - django-extensions - Pillow + - pyaml - django-bootstrap3 executable: pip3 diff --git a/ansible/roles/web_AI-5/tasks/setup_script.sh b/ansible/roles/web_AI-5/tasks/setup_script.sh index d9ed1c3..6243fb4 100755 --- a/ansible/roles/web_AI-5/tasks/setup_script.sh +++ b/ansible/roles/web_AI-5/tasks/setup_script.sh @@ -17,3 +17,5 @@ echo "from django.contrib.auth.models import User; \ User.objects.filter(email='admin@example.com').delete(); \ User.objects.create_superuser('admin', 'admin@example.com', 'password')" | python3 /vagrant/django/didgeridoo/manage.py shell + +python3 /vagrant/django/didgeridoo/manage.py loaddata webshop diff --git a/django/.idea/django.iml b/django/.idea/django.iml index 6711606..0acd853 100644 --- a/django/.idea/django.iml +++ b/django/.idea/django.iml @@ -2,7 +2,7 @@ - + diff --git a/django/.idea/misc.xml b/django/.idea/misc.xml index 2c50d4f..539c015 100644 --- a/django/.idea/misc.xml +++ b/django/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/django/didgeridoo/currencies/__init__.py b/django/didgeridoo/currencies/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/didgeridoo/currencies/admin.py b/django/didgeridoo/currencies/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/django/didgeridoo/currencies/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/django/didgeridoo/currencies/apps.py b/django/didgeridoo/currencies/apps.py new file mode 100644 index 0000000..055501d --- /dev/null +++ b/django/didgeridoo/currencies/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CurrenciesConfig(AppConfig): + name = 'currencies' diff --git a/django/didgeridoo/currencies/exchange_rates.py b/django/didgeridoo/currencies/exchange_rates.py new file mode 100644 index 0000000..bb12c47 --- /dev/null +++ b/django/didgeridoo/currencies/exchange_rates.py @@ -0,0 +1,124 @@ +from datetime import datetime +import urllib.request +import xml.etree.ElementTree as ET + +today = datetime.now().strftime("%Y-%m-%d") + +""" this method calls a rss/XML Resource + of Currency's and parses it to our + needed exchange rate values. + The return is a dictionary carring + Key:Value pairs of new currencys. +""" + + +def get_exchange_rate(): + # During weekends there are no updates. + # To develop i need a testresource. + # In that case i comment the Online Resource block and uncomment the + # development Block... + # ~~~~~~~~~~~~~~~~~~~~~ + # Online Resource block: + # ~~~~~~~~~~~~~~~~~~~~~ + SNB_URL = 'https://www.snb.ch/selector/de/mmr/exfeed/rss' + urlsocket = urllib.request.urlopen(SNB_URL) + root = ET.parse(urlsocket) + root = ET.ElementTree(root) + + # ~~~~~~~~~~~~~~~~~~~~~ + # development block: + # ~~~~~~~~~~~~~~~~~~~~~ + # root = ET.ElementTree(file='rss') + # ~~~~~~~~~~~~~~~~~~~~~ + # Namespaces + ns = {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'none': 'http://purl.org/rss/1.0/', + 'dc': 'http://purl.org/dc/elements/1.1/', + 'dcterms': 'http://purl.org/dc/terms/', + 'cb': 'http://www.cbwiki.net/wiki/index.php/Specification_1.2/' + } + # Pathvariables to XML Namespaces + none_path = 'none:item/' + rate_path = 'cb:statistics/cb:exchangeRate/' + observation_path = 'cb:statistics/cb:exchangeRate/cb:observation/' + # THE FILE DATE: + xml_datetime_string = root.find('none:channel/dcterms:created', ns).text + # because of few knowlede just trim end of string to avoid error + xml_datestring = xml_datetime_string.split('T')[0] + # parse string to date object: + xml_date = datetime.date(datetime.strptime(xml_datestring, "%Y-%m-%d")) + exchange_rates = {} + for item in root.findall('none:item', ns): + # THE CURRENCY DATE: + datetime_str = item.find('dc:date', ns).text + # convert string to date object: + # https://stackoverflow.com/a/12282040/4061870 + # seams like snb striked the microsecond somewhere between Nov. and + # Dez. 2017 so maybe first check time type. "%Y-%m-%dT%H:%M:%S.%f%z" + date = datetime.strptime(''.join( + datetime_str.rsplit(':', 1)), + "%Y-%m-%dT%H:%M:%S%z").strftime( + "%Y-%m-%d") + # only the values of today are used so check for date in XML: + if date == today: + title = item.find('none:title', ns).text + base_currency = item.find(rate_path + + 'cb:baseCurrency', ns).text + target_currency = item.find(rate_path + + 'cb:targetCurrency', ns).text + CHFvalue = float(item.find(observation_path + + 'cb:value', ns).text) + CHFvalue = float(CHFvalue) # convert to float + FOREIGNvalue = CHFvalue # copy to new value to have both. + unit = item.find(observation_path + 'cb:unit', ns).text + decimals = int(item.find(observation_path + + 'cb:decimals', ns).text) + # because it's dangerous to check for present, i check for none + # here and have to do something in there so i set the target to 0. + if item.find(observation_path + 'cb:unit_mult', ns) is None: + unit_mult = float("1.0") + else: + # shift left by 2 digits with "/" + # https://stackoverflow.com/questions/8362792/ + # because some currencys differ widly from CHF + unit_mult = item.find(observation_path + + 'cb:unit_mult', ns).text + # unit_mult defaults to '0' so we check for 8 decimal + # values (2..-6) they represent the fracton value to + # calculate the correct decimalpoint. + if unit_mult == '2': # thinking of Bitcoins + unit_mult = '0.01' + if unit_mult == '1': + unit_mult = '0.10' + if unit_mult == '-1': + unit_mult = '10' + if unit_mult == '-2': # Japan Yen + unit_mult = '100' + if unit_mult == '-3': + unit_mult = '1000' + if unit_mult == '-4': + unit_mult = '10000' + if unit_mult == '-5': + unit_mult = '100000' + if unit_mult == '-6': # indian rupies + unit_mult = '1000000' + unit_mult = float(unit_mult) # convert to float + # calculate the Currency to CHF: + FOREIGNvalue = 1 / CHFvalue + FOREIGNvalue *= unit_mult + CHFvalue = CHFvalue / unit_mult + # truncate it to decimal values provided by the xml: + FOREIGNvalue_round = round(FOREIGNvalue, 5) + # Print nice setup of all calculated currencys for Dev: + # print("date:", date, " 1 ", target_currency, " costs: ", + # CHFvalue, "CHF and 1 ", base_currency, " costs: ", + # FOREIGNvalue_round, target_currency) + exchange_rates.update( + {target_currency: FOREIGNvalue_round}) + # Print the Dictionary: + # print(exchange_rates) + else: + break + return(exchange_rates, date) + # for development its preferable to see that the for loop is done: + # print('no more fresh data!') diff --git a/django/didgeridoo/currencies/migrations/0001_initial.py b/django/didgeridoo/currencies/migrations/0001_initial.py new file mode 100644 index 0000000..c7f74a7 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-18 18:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='ExchangeRate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, unique=True)), + ('exchange_rate_to_chf', models.FloatField(max_length=5)), + ], + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0002_exchangerate_date.py b/django/didgeridoo/currencies/migrations/0002_exchangerate_date.py new file mode 100644 index 0000000..37fb831 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0002_exchangerate_date.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-27 10:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='exchangerate', + name='date', + field=models.DateField(null=True), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0003_auto_20171227_1119.py b/django/didgeridoo/currencies/migrations/0003_auto_20171227_1119.py new file mode 100644 index 0000000..c6283a2 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0003_auto_20171227_1119.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-27 10:19 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0002_exchangerate_date'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='date', + field=models.DateField(null=True, verbose_name='%Y-%m-%d'), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0004_auto_20171229_1708.py b/django/didgeridoo/currencies/migrations/0004_auto_20171229_1708.py new file mode 100644 index 0000000..ad84626 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0004_auto_20171229_1708.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-29 16:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0003_auto_20171227_1119'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='name', + field=models.CharField(max_length=200), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0005_auto_20171229_1735.py b/django/didgeridoo/currencies/migrations/0005_auto_20171229_1735.py new file mode 100644 index 0000000..3ac6227 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0005_auto_20171229_1735.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-29 16:35 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0004_auto_20171229_1708'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='date', + field=models.DateField(null=True, verbose_name='%Y-%m-%dT%H:%M:%S'), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0006_auto_20171229_1747.py b/django/didgeridoo/currencies/migrations/0006_auto_20171229_1747.py new file mode 100644 index 0000000..a2a330b --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0006_auto_20171229_1747.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-29 16:47 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0005_auto_20171229_1735'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='date', + field=models.DateTimeField(null=True, verbose_name='%Y-%m-%dT%H:%M:%S'), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/0007_auto_20171229_1806.py b/django/didgeridoo/currencies/migrations/0007_auto_20171229_1806.py new file mode 100644 index 0000000..2455467 --- /dev/null +++ b/django/didgeridoo/currencies/migrations/0007_auto_20171229_1806.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-29 17:06 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('currencies', '0006_auto_20171229_1747'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='date', + field=models.DateField(null=True, verbose_name='%Y-%m-%d'), + ), + ] diff --git a/django/didgeridoo/currencies/migrations/__init__.py b/django/didgeridoo/currencies/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/didgeridoo/currencies/models.py b/django/didgeridoo/currencies/models.py new file mode 100644 index 0000000..ca6ed15 --- /dev/null +++ b/django/didgeridoo/currencies/models.py @@ -0,0 +1,10 @@ +from django.db import models + + +class ExchangeRate(models.Model): + name = models.CharField(max_length=200) + date = models.DateField('%Y-%m-%d', null=True) + exchange_rate_to_chf = models.FloatField(max_length=5) + + def __str__(self): + return self.name diff --git a/django/didgeridoo/currencies/templates/currencies/index.html b/django/didgeridoo/currencies/templates/currencies/index.html new file mode 100644 index 0000000..bddcee2 --- /dev/null +++ b/django/didgeridoo/currencies/templates/currencies/index.html @@ -0,0 +1,42 @@ + + + + + +
+

Currencies in CHF

+ {% if currency_list %} + + + + {% for currency in currency_list %} + + {% endfor %} + + + + {% for currency in currency_list %} + + {% endfor %} + +
DATE{{ currency.name }}
{{ date }}{{ currency.exchange_rate_to_chf }}
+
+

{{ message }}

+
+
    + {% for currency in currency_list %} +
  • + {{ currency.date }} : + {{ currency.name }} : + {{ currency.exchange_rate_to_chf }} +
  • + {% endfor %} +
+ {% else %} +

+ Something whent wrong, no currencies are available. +

+ {% endif %} +
+ + diff --git a/django/didgeridoo/currencies/tests.py b/django/didgeridoo/currencies/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/django/didgeridoo/currencies/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/django/didgeridoo/currencies/urls.py b/django/didgeridoo/currencies/urls.py new file mode 100644 index 0000000..2804c74 --- /dev/null +++ b/django/didgeridoo/currencies/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import url +from currencies.views import currencies + + +urlpatterns = [ + url(r'^currencies/$', currencies), +] diff --git a/django/didgeridoo/currencies/views.py b/django/didgeridoo/currencies/views.py new file mode 100644 index 0000000..1128eab --- /dev/null +++ b/django/didgeridoo/currencies/views.py @@ -0,0 +1,26 @@ +from django.shortcuts import render +from currencies.models import ExchangeRate +from currencies import exchange_rates + + +def currencies(request): + # return HttpResponse("exchange_rates") + raw_data, date = exchange_rates.get_exchange_rate() + message = "" + for currency, rate in raw_data.items(): + if ExchangeRate.objects.filter(date=date): + message = "already querried today" + else: + e = ExchangeRate.objects.create( + name=currency, + exchange_rate_to_chf=rate, + date=date + ) + e.save() + message = "updated successfully" + currency_list = ExchangeRate.objects.all() + return render(request, + 'currencies/index.html', + {'currency_list': currency_list, + 'date': date, + 'message': message}) diff --git a/django/didgeridoo/didgeridoo/settings.py b/django/didgeridoo/didgeridoo/settings.py index dbe98ed..67fac21 100644 --- a/django/didgeridoo/didgeridoo/settings.py +++ b/django/didgeridoo/didgeridoo/settings.py @@ -23,9 +23,13 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '(#4#-$$&mx7(%q+6&&@-c&g%i0dc4)zfks1%sy8b%lsxspou&%' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = False -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = [ + 'localhost', + '127.0.0.1', + 'didgeridoo.ml' +] # Application definition @@ -39,8 +43,9 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'bootstrap3' -] + 'currencies', + 'bootstrap3', + ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', @@ -131,9 +136,4 @@ STATIC_URL = '/static/' STATIC_ROOT = '/vagrant/django/didgeridoo/static/' MEDIA_ROOT = '/vagrant/django/didgeridoo/media/' - -ALLOWED_HOSTS = [ - 'localhost', - '127.0.0.1', - 'didgeridoo.ml' -] +LOGIN_REDIRECT_URL = '/' diff --git a/django/didgeridoo/didgeridoo/urls.py b/django/didgeridoo/didgeridoo/urls.py index 1eef47b..a9524c5 100644 --- a/django/didgeridoo/didgeridoo/urls.py +++ b/django/didgeridoo/didgeridoo/urls.py @@ -18,6 +18,6 @@ from django.contrib import admin urlpatterns = [ url(r'', include('webshop.urls')), - url(r'^admin/', admin.site.urls), + url(r'', include('currencies.urls')), url(r'^admin/', admin.site.urls), ] diff --git a/django/didgeridoo/rss b/django/didgeridoo/rss new file mode 100644 index 0000000..af36b76 --- /dev/null +++ b/django/didgeridoo/rss @@ -0,0 +1,621 @@ + + + + SNB Devisenkurse + https://www.snb.ch/de/ifor/media/id/media_rss + Schweizerische Nationalbank (SNB): Devisenkurse (Ankauf Zürich 11 Uhr) + + + + + + + + + + + + + + + + + + + + + + + + + SNB + Copyright © Schweizerische Nationalbank, Zürich (Schweiz) 2017 + https://www.snb.ch/de/srv/id/disclaimer + 2017-11-28T07:50:22+01:00 + + + CH: 1.3081 CHF = 1 GBP 2017-11-27 Tägliche Kurse (11:00) + https://www.snb.ch + 1 GBP = 1.3081 CHF (Tägliche Kurse (11:00); 2017-11-27T12:16:53.767+01:00) + 2017-12-19T12:16:53.767+01:00 + de + + + CH + SNB + + + + + 1.3081 + CHF + 4 + + CHF + GBP + Tägliche Kurse (11:00) + + + daily + 2017-11-27 + + + + + + CH: 0.8813 CHF = 100 JPY 2017-11-27 Tägliche Kurse (11:00) + https://www.snb.ch + 100 JPY = 0.8813 CHF (Tägliche Kurse (11:00); 2017-11-27T12:16:53.760+01:00) + 2017-12-19T12:16:53.760+01:00 + de + + + CH + SNB + + + + + 10000.8813 + CHF + -2 + 4 + + CHF + JPY + Tägliche Kurse (11:00) + + + daily + 2017-11-27 + + + + + + CH: 1.1697 CHF = 1 EUR 2017-11-27 Tägliche Kurse (11:00) + https://www.snb.ch + 1 EUR = 1.1697 CHF (Tägliche Kurse (11:00); 2017-11-27T12:16:53.750+01:00) + 2017-12-19T12:16:53.750+01:00 + de + + + CH + SNB + + + + + 1.1697 + CHF + 4 + + CHF + EUR + Tägliche Kurse (11:00) + + + daily + 2017-11-27 + + + + + + CH: 0.9803 CHF = 1 USD 2017-11-27 Tägliche Kurse (11:00) + https://www.snb.ch + 1 USD = 0.9803 CHF (Tägliche Kurse (11:00); 2017-11-27T12:16:53.737+01:00) + 2017-11-29T12:16:53.737+01:00 + de + + + CH + SNB + + + + + 0.9803 + CHF + 4 + + CHF + USD + Tägliche Kurse (11:00) + + + daily + 2017-11-27 + + + + + + CH: 1.3072 CHF = 1 GBP 2017-11-24 Tägliche Kurse (11:00) + https://www.snb.ch + 1 GBP = 1.3072 CHF (Tägliche Kurse (11:00); 2017-11-24T12:19:49.733+01:00) + 2017-11-24T12:19:49.733+01:00 + de + + + CH + SNB + + + + + 1.3072 + CHF + 4 + + CHF + GBP + Tägliche Kurse (11:00) + + + daily + 2017-11-24 + + + + + + CH: 0.8806 CHF = 100 JPY 2017-11-24 Tägliche Kurse (11:00) + https://www.snb.ch + 100 JPY = 0.8806 CHF (Tägliche Kurse (11:00); 2017-11-24T12:19:49.717+01:00) + 2017-11-24T12:19:49.717+01:00 + de + + + CH + SNB + + + + + 0.8806 + CHF + -2 + 4 + + CHF + JPY + Tägliche Kurse (11:00) + + + daily + 2017-11-24 + + + + + + CH: 1.1644 CHF = 1 EUR 2017-11-24 Tägliche Kurse (11:00) + https://www.snb.ch + 1 EUR = 1.1644 CHF (Tägliche Kurse (11:00); 2017-11-24T12:19:49.710+01:00) + 2017-11-24T12:19:49.710+01:00 + de + + + CH + SNB + + + + + 1.1644 + CHF + 4 + + CHF + EUR + Tägliche Kurse (11:00) + + + daily + 2017-11-24 + + + + + + CH: 0.9809 CHF = 1 USD 2017-11-24 Tägliche Kurse (11:00) + https://www.snb.ch + 1 USD = 0.9809 CHF (Tägliche Kurse (11:00); 2017-11-24T12:19:49.703+01:00) + 2017-11-24T12:19:49.703+01:00 + de + + + CH + SNB + + + + + 0.9809 + CHF + 4 + + CHF + USD + Tägliche Kurse (11:00) + + + daily + 2017-11-24 + + + + + + CH: 1.3052 CHF = 1 GBP 2017-11-23 Tägliche Kurse (11:00) + https://www.snb.ch + 1 GBP = 1.3052 CHF (Tägliche Kurse (11:00); 2017-11-23T12:36:46.040+01:00) + 2017-11-23T12:36:46.040+01:00 + de + + + CH + SNB + + + + + 1.3052 + CHF + 4 + + CHF + GBP + Tägliche Kurse (11:00) + + + daily + 2017-11-23 + + + + + + CH: 0.8816 CHF = 100 JPY 2017-11-23 Tägliche Kurse (11:00) + https://www.snb.ch + 100 JPY = 0.8816 CHF (Tägliche Kurse (11:00); 2017-11-23T12:36:46.030+01:00) + 2017-11-23T12:36:46.030+01:00 + de + + + CH + SNB + + + + + 0.8816 + CHF + -2 + 4 + + CHF + JPY + Tägliche Kurse (11:00) + + + daily + 2017-11-23 + + + + + + CH: 1.1617 CHF = 1 EUR 2017-11-23 Tägliche Kurse (11:00) + https://www.snb.ch + 1 EUR = 1.1617 CHF (Tägliche Kurse (11:00); 2017-11-23T12:36:46.027+01:00) + 2017-11-23T12:36:46.027+01:00 + de + + + CH + SNB + + + + + 1.1617 + CHF + 4 + + CHF + EUR + Tägliche Kurse (11:00) + + + daily + 2017-11-23 + + + + + + CH: 0.9811 CHF = 1 USD 2017-11-23 Tägliche Kurse (11:00) + https://www.snb.ch + 1 USD = 0.9811 CHF (Tägliche Kurse (11:00); 2017-11-23T12:36:46.017+01:00) + 2017-11-23T12:36:46.017+01:00 + de + + + CH + SNB + + + + + 0.9811 + CHF + 4 + + CHF + USD + Tägliche Kurse (11:00) + + + daily + 2017-11-23 + + + + + + CH: 1.3109 CHF = 1 GBP 2017-11-22 Tägliche Kurse (11:00) + https://www.snb.ch + 1 GBP = 1.3109 CHF (Tägliche Kurse (11:00); 2017-11-22T12:24:04.110+01:00) + 2017-11-22T12:24:04.110+01:00 + de + + + CH + SNB + + + + + 1.3109 + CHF + 4 + + CHF + GBP + Tägliche Kurse (11:00) + + + daily + 2017-11-22 + + + + + + CH: 0.8827 CHF = 100 JPY 2017-11-22 Tägliche Kurse (11:00) + https://www.snb.ch + 100 JPY = 0.8827 CHF (Tägliche Kurse (11:00); 2017-11-22T12:24:04.103+01:00) + 2017-11-22T12:24:04.103+01:00 + de + + + CH + SNB + + + + + 0.8827 + CHF + -2 + 4 + + CHF + JPY + Tägliche Kurse (11:00) + + + daily + 2017-11-22 + + + + + + CH: 1.1633 CHF = 1 EUR 2017-11-22 Tägliche Kurse (11:00) + https://www.snb.ch + 1 EUR = 1.1633 CHF (Tägliche Kurse (11:00); 2017-11-22T12:24:04.090+01:00) + 2017-11-22T12:24:04.090+01:00 + de + + + CH + SNB + + + + + 1.1633 + CHF + 4 + + CHF + EUR + Tägliche Kurse (11:00) + + + daily + 2017-11-22 + + + + + + CH: 0.9894 CHF = 1 USD 2017-11-22 Tägliche Kurse (11:00) + https://www.snb.ch + 1 USD = 0.9894 CHF (Tägliche Kurse (11:00); 2017-11-22T12:24:04.083+01:00) + 2017-11-22T12:24:04.083+01:00 + de + + + CH + SNB + + + + + 0.9894 + CHF + 4 + + CHF + USD + Tägliche Kurse (11:00) + + + daily + 2017-11-22 + + + + + + CH: 1.3151 CHF = 1 GBP 2017-11-21 Tägliche Kurse (11:00) + https://www.snb.ch + 1 GBP = 1.3151 CHF (Tägliche Kurse (11:00); 2017-11-21T12:19:20.370+01:00) + 2017-11-21T12:19:20.370+01:00 + de + + + CH + SNB + + + + + 1.3151 + CHF + 4 + + CHF + GBP + Tägliche Kurse (11:00) + + + daily + 2017-11-21 + + + + + + CH: 0.8832 CHF = 100 JPY 2017-11-21 Tägliche Kurse (11:00) + https://www.snb.ch + 100 JPY = 0.8832 CHF (Tägliche Kurse (11:00); 2017-11-21T12:19:20.363+01:00) + 2017-11-21T12:19:20.363+01:00 + de + + + CH + SNB + + + + + 0.8832 + CHF + -2 + 4 + + CHF + JPY + Tägliche Kurse (11:00) + + + daily + 2017-11-21 + + + + + + CH: 1.1647 CHF = 1 EUR 2017-11-21 Tägliche Kurse (11:00) + https://www.snb.ch + 1 EUR = 1.1647 CHF (Tägliche Kurse (11:00); 2017-11-21T12:19:20.360+01:00) + 2017-11-21T12:19:20.360+01:00 + de + + + CH + SNB + + + + + 1.1647 + CHF + 4 + + CHF + EUR + Tägliche Kurse (11:00) + + + daily + 2017-11-21 + + + + + + CH: 0.9930 CHF = 1 USD 2017-11-21 Tägliche Kurse (11:00) + https://www.snb.ch + 1 USD = 0.9930 CHF (Tägliche Kurse (11:00); 2017-11-21T12:19:20.343+01:00) + 2017-11-21T12:19:20.343+01:00 + de + + + CH + SNB + + + + + 0.9930 + CHF + 4 + + CHF + USD + Tägliche Kurse (11:00) + + + daily + 2017-11-21 + + + + + diff --git a/django/didgeridoo/webshop/admin.py b/django/didgeridoo/webshop/admin.py index 1abf027..06b4dd4 100644 --- a/django/didgeridoo/webshop/admin.py +++ b/django/didgeridoo/webshop/admin.py @@ -3,8 +3,9 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.models import User # Register your models here. -from .models import (Article, Order, OrderPosition, Person, City, Picture, - OrderOfGoods, Category, Option, Setting) +from webshop.models import (Article, Order, OrderPosition, + Person, City, Picture, OrderOfGoods, + Category, Option, Setting) class PersonInline(admin.StackedInline): diff --git a/django/didgeridoo/webshop/fixtures/webshop.yaml b/django/didgeridoo/webshop/fixtures/webshop.yaml new file mode 100644 index 0000000..a3c429d --- /dev/null +++ b/django/didgeridoo/webshop/fixtures/webshop.yaml @@ -0,0 +1,97 @@ +- model: webshop.Category + fields: + name: "First Parent Category" + parent_category: +- model: webshop.Category + fields: + name: "Second Parent Category" + parent_category: +- model: webshop.Category + fields: + name: "Third Parent Category" + parent_category: +- model: webshop.Category + fields: + name: "Fourth Parent Category" + parent_category: +- model: webshop.Category + fields: + name: "Child Category 1" + parent_category: 1 +- model: webshop.Category + fields: + name: "Child Category 2" + parent_category: 2 +- model: webshop.Category + fields: + name: "Child Category 3" + parent_category: 3 +- model: webshop.Category + fields: + name: "Child Category 4" + parent_category: 4 + +- model: webshop.Article + fields: + name: "Article of First Parent Category" + category: 1 + description: "An article sorted under the First Parent Category." + stock: 10 + status: 3 + price_in_chf: 10.1 +- model: webshop.Article + fields: + name: "Article of Second Parent Category" + category: 2 + description: "An article sorted under the Second Parent Category." + stock: 20 + status: 3 + price_in_chf: 20.2 +- model: webshop.Article + fields: + name: "Article of Third Parent Category" + category: 3 + description: "An article sorted under the Third Parent Category." + stock: 30 + status: 3 + price_in_chf: 30.3 +- model: webshop.Article + fields: + name: "Article of Fourth Parent Category" + category: 4 + description: "An article sorted under the Fourth Parent Category." + stock: 40 + status: 3 + price_in_chf: 40.4 +- model: webshop.Article + fields: + name: "Article of Child Category 1" + category: 5 + description: "An article sorted under the Child Category 1." + stock: 11 + status: 3 + price_in_chf: 11.1 +- model: webshop.Article + fields: + name: "Article of Child Category 2" + category: 6 + description: "An article sorted under the Child Category 2." + stock: 22 + status: 3 + price_in_chf: 21.2 +- model: webshop.Article + fields: + name: "Article of Child Category 3" + category: 7 + description: "An article sorted under the Child Category 3." + stock: 33 + status: 3 + price_in_chf: 31.3 +- model: webshop.Article + fields: + name: "Article of Child Category 4" + category: 8 + description: "An article sorted under the Child Category 4." + stock: 44 + status: 3 + price_in_chf: 41.4 diff --git a/django/didgeridoo/webshop/forms.py b/django/didgeridoo/webshop/forms.py new file mode 100644 index 0000000..c87ec6c --- /dev/null +++ b/django/didgeridoo/webshop/forms.py @@ -0,0 +1,24 @@ +from django import forms +from webshop.models import Salutation, City + + +class RegistrationForm(forms.Form): + email = forms.EmailField() + salutation = forms.ModelChoiceField(queryset=Salutation.objects.all()) + first_name = forms.CharField() + last_name = forms.CharField() + street_name = forms.CharField() + street_number = forms.CharField() + zip_code = forms.IntegerField(min_value=1000, max_value=9999) + city = forms.CharField() + + def clean_city(self): + # Check that the two password entries match + city = self.cleaned_data['city'] + zip_code = self.cleaned_data['zip_code'] + try: + City.objects.get(name=city, zip_code=zip_code) + except City.DoesNotExist: + raise forms.ValidationError( + "The zip code and the city don't match.") + return city diff --git a/django/didgeridoo/webshop/models.py b/django/didgeridoo/webshop/models.py index b2bfa91..ecb6678 100644 --- a/django/didgeridoo/webshop/models.py +++ b/django/didgeridoo/webshop/models.py @@ -1,5 +1,3 @@ -#!/usr/bin/python3 - from decimal import Decimal from django.core.validators import MinValueValidator from django.db import models @@ -30,14 +28,6 @@ class ArticleStatus(models.Model): return self.name -class ExchangeRate(models.Model): - name = models.CharField(max_length=200, unique=True) - exchange_rate_to_chf = models.FloatField(max_length=5) - - def __str__(self): - return self.name - - # Create your models here. class Category(models.Model): name = models.CharField(max_length=200, unique=True) @@ -138,8 +128,6 @@ class Salutation(models.Model): class Person(models.Model): - first_name = models.CharField(max_length=200) - last_name = models.CharField(max_length=200) salutation = models.ForeignKey(Salutation) city = models.ForeignKey(City) street_name = models.CharField(max_length=200) @@ -147,4 +135,4 @@ class Person(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) def __str__(self): - return self.last_name + return self.user.username diff --git a/django/didgeridoo/webshop/templates/registration/logged_out.html b/django/didgeridoo/webshop/templates/registration/logged_out.html new file mode 100644 index 0000000..866f568 --- /dev/null +++ b/django/didgeridoo/webshop/templates/registration/logged_out.html @@ -0,0 +1,6 @@ +{% extends 'webshop/base.html' %} + +{% block section_title %}You have been successfully logged out.{% endblock %} + +{% block content %} +{% endblock %} diff --git a/django/didgeridoo/webshop/templates/registration/login.html b/django/didgeridoo/webshop/templates/registration/login.html new file mode 100644 index 0000000..4ff603e --- /dev/null +++ b/django/didgeridoo/webshop/templates/registration/login.html @@ -0,0 +1,12 @@ +{% extends 'webshop/base.html' %} + +{% block section_title %}Login{% endblock %} + +{% block content %} +
+ {% csrf_token %} + {{ form.as_p }} + +

Go to registration.

+
+{% endblock %} diff --git a/django/didgeridoo/webshop/templates/registration/profile.html b/django/didgeridoo/webshop/templates/registration/profile.html new file mode 100644 index 0000000..ed2e406 --- /dev/null +++ b/django/didgeridoo/webshop/templates/registration/profile.html @@ -0,0 +1,17 @@ +{% extends 'webshop/base.html' %} + +{% block section_title %}User Profile{% endblock %} + +{% block content %} +

Username: {{ request.user.username }}

+

Salutation: {{ person.salutation }}

+

Firstname: {{ request.user.first_name }}

+

Lastname: {{ request.user.last_name }}

+

City: {{ person.city }}

+

Street: {{ person.street_name }}

+

Streetnumber: {{ person.street_number }}

+
+ {% csrf_token %} + {{ form.as_p }} +
+{% endblock %} diff --git a/django/didgeridoo/webshop/templates/registration/register.html b/django/didgeridoo/webshop/templates/registration/register.html new file mode 100644 index 0000000..032758f --- /dev/null +++ b/django/didgeridoo/webshop/templates/registration/register.html @@ -0,0 +1,19 @@ +{% extends 'webshop/base.html' %} + +{% block section_title %}Registration{% endblock %} + +{% block content %} + {% if profile_form.errors %} +

+ Please correct the error{{ form.errors|pluralize }} below. +

+ {% endif %} +
+ + {{ user_form.as_table }} + {{ profile_form.as_table }} +
+ {% csrf_token %} + +
+{% endblock %} diff --git a/django/didgeridoo/webshop/templates/webshop/base.html b/django/didgeridoo/webshop/templates/webshop/base.html index 8cd2aa6..c1d1e54 100644 --- a/django/didgeridoo/webshop/templates/webshop/base.html +++ b/django/didgeridoo/webshop/templates/webshop/base.html @@ -16,6 +16,16 @@ {% endblock %} +
+ Home | + {% if user.is_authenticated %} + Profile | Logout + {% else %} + Login + {% endif %} +

{% block section_title %}Music Instrument Shop{% endblock %}

+ {% block content %}{% endblock %} +
diff --git a/django/didgeridoo/webshop/urls.py b/django/didgeridoo/webshop/urls.py index ae62468..dc79c1d 100644 --- a/django/didgeridoo/webshop/urls.py +++ b/django/didgeridoo/webshop/urls.py @@ -1,6 +1,6 @@ -from django.conf.urls import url +from django.conf.urls import url, include -from . import views +from webshop import views urlpatterns = [ url(r'^$', views.index, name='index'), @@ -10,4 +10,7 @@ urlpatterns = [ url(r'^category/(?P[0-9]+)/$', views.articles_in_category, name='category'), + url('^', include('django.contrib.auth.urls')), + url(r'^profile/$', views.profile, name='profile'), + url(r'^registration/$', views.registration, name='registration'), ] diff --git a/django/didgeridoo/webshop/views.py b/django/didgeridoo/webshop/views.py index 046ae5f..499c261 100644 --- a/django/didgeridoo/webshop/views.py +++ b/django/didgeridoo/webshop/views.py @@ -1,5 +1,10 @@ +from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render -from .models import Article, Category, ArticleStatus +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm +from webshop.models import Article, Category, ArticleStatus, Person, City +from webshop.forms import RegistrationForm # Create your views here. @@ -33,3 +38,39 @@ def article_details(request, article_id): article = get_object_or_404(Article, pk=article_id) return render(request, 'webshop/article_details.html', {'article': article}) + + +@login_required +def profile(request): + person = Person.objects.get(user=request.user) + return render(request, 'registration/profile.html', + {'person': person}) + + +def registration(request): + if request.method == 'POST': + profile_form = RegistrationForm(request.POST) + user_form = UserCreationForm(request.POST) + if (profile_form.is_valid() and user_form.is_valid()): + pf = profile_form.cleaned_data + uf = user_form.cleaned_data + user = User.objects.create_user(uf['username'], + pf['email'], + uf['password2']) + user.last_name = pf['last_name'] + user.first_name = pf['first_name'] + user.save() + person = Person.objects.create( + salutation=pf['salutation'], + city=City.objects.get(zip_code=pf['zip_code'], + name=pf['city']), + street_name=pf['street_name'], + street_number=pf['street_number'], + user=user) + return HttpResponseRedirect('/login/') + else: + profile_form = RegistrationForm + user_form = UserCreationForm + return render(request, 'registration/register.html', + {'profile_form': profile_form, + 'user_form': user_form}) diff --git a/docs/main.tex b/docs/main.tex index 3c774f0..fa3976b 100644 --- a/docs/main.tex +++ b/docs/main.tex @@ -11,7 +11,7 @@ \microtypesetup{protrusion=true} % enables protrusion \newpage -\include{content} +\include{doku} \newpage \nocite{*} diff --git a/html/index.html b/html/index.html deleted file mode 100644 index 6bc0653..0000000 --- a/html/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -
-

audioguide

-

a mobile offline audioguide

- noop - noop - noop - noop - noop - noop -

the audioguide that makes a offline usage possible.

-
- - - diff --git a/sql/02_insert_data.sql b/sql/02_insert_data.sql index 6689176..8c31e0b 100644 --- a/sql/02_insert_data.sql +++ b/sql/02_insert_data.sql @@ -24,7 +24,7 @@ use webshopdb; insert into webshop_articlestatus (name) values ('out of stock'), ('hidden'), - ('on sale'); + ('active'); use webshopdb; insert into webshop_city (zip_code, name)