From 4579880d4724a5357757e8629bc91bdae17dbf4f Mon Sep 17 00:00:00 2001 From: Jannes Hikmat Date: Thu, 5 Jan 2023 03:32:57 +0100 Subject: [PATCH] =?UTF-8?q?Gruppenaufgaben=205=20&=206=20=C3=BCberarbeitet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manage.py | 22 +++ mensaviewer/__init__.py | 0 mensaviewer/admin.py | 23 +++ mensaviewer/apps.py | 6 + mensaviewer/data.py | 16 ++ mensaviewer/forms.py | 11 ++ mensaviewer/helpers.py | 142 ++++++++++++++++++ mensaviewer/migrations/0001_initial.py | 48 ++++++ .../migrations/0002_alter_menu_date.py | 18 +++ .../migrations/0003_alter_menu_date.py | 18 +++ ...menu_date_remove_menu_mensa_id_and_more.py | 88 +++++++++++ ..._rename_related_menus_menu_related_days.py | 18 +++ ...enu_allergens_remove_menu_tags_and_more.py | 50 ++++++ .../migrations/0007_allergen_name_tag_name.py | 23 +++ .../0008_rename_tag_type_and_more.py | 27 ++++ .../migrations/0009_rename_type_menu_art.py | 18 +++ ..._days_day_menus_alter_day_date_and_more.py | 37 +++++ ...ename_related_meal_comment_related_menu.py | 18 +++ ...day_menus_remove_menu_dislikes_and_more.py | 84 +++++++++++ mensaviewer/migrations/0013_menu_price.py | 18 +++ ..._menu_day_remove_menu_location_and_more.py | 38 +++++ .../migrations/0015_comment_timestamp.py | 19 +++ mensaviewer/migrations/__init__.py | 0 mensaviewer/models.py | 60 ++++++++ mensaviewer/templates/base.html | 23 +++ mensaviewer/templates/comment.html | 10 ++ mensaviewer/templates/create_location.html | 11 ++ mensaviewer/templates/flensburg.html | 69 +++++++++ mensaviewer/templates/menu_detail.html | 27 ++++ mensaviewer/tests.py | 3 + mensaviewer/urls.py | 12 ++ mensaviewer/views.py | 75 +++++++++ static/base.css | 33 ++++ webprog/__init__.py | 0 webprog/asgi.py | 16 ++ webprog/settings.py | 128 ++++++++++++++++ webprog/urls.py | 22 +++ webprog/wsgi.py | 16 ++ 38 files changed, 1247 insertions(+) create mode 100644 manage.py create mode 100644 mensaviewer/__init__.py create mode 100644 mensaviewer/admin.py create mode 100644 mensaviewer/apps.py create mode 100644 mensaviewer/data.py create mode 100644 mensaviewer/forms.py create mode 100644 mensaviewer/helpers.py create mode 100644 mensaviewer/migrations/0001_initial.py create mode 100644 mensaviewer/migrations/0002_alter_menu_date.py create mode 100644 mensaviewer/migrations/0003_alter_menu_date.py create mode 100644 mensaviewer/migrations/0004_day_remove_menu_date_remove_menu_mensa_id_and_more.py create mode 100644 mensaviewer/migrations/0005_rename_related_menus_menu_related_days.py create mode 100644 mensaviewer/migrations/0006_allergen_tag_remove_menu_allergens_remove_menu_tags_and_more.py create mode 100644 mensaviewer/migrations/0007_allergen_name_tag_name.py create mode 100644 mensaviewer/migrations/0008_rename_tag_type_and_more.py create mode 100644 mensaviewer/migrations/0009_rename_type_menu_art.py create mode 100644 mensaviewer/migrations/0010_remove_menu_related_days_day_menus_alter_day_date_and_more.py create mode 100644 mensaviewer/migrations/0011_rename_related_meal_comment_related_menu.py create mode 100644 mensaviewer/migrations/0012_location_remove_day_menus_remove_menu_dislikes_and_more.py create mode 100644 mensaviewer/migrations/0013_menu_price.py create mode 100644 mensaviewer/migrations/0014_day_remove_menu_day_remove_menu_location_and_more.py create mode 100644 mensaviewer/migrations/0015_comment_timestamp.py create mode 100644 mensaviewer/migrations/__init__.py create mode 100644 mensaviewer/models.py create mode 100644 mensaviewer/templates/base.html create mode 100644 mensaviewer/templates/comment.html create mode 100644 mensaviewer/templates/create_location.html create mode 100644 mensaviewer/templates/flensburg.html create mode 100644 mensaviewer/templates/menu_detail.html create mode 100644 mensaviewer/tests.py create mode 100644 mensaviewer/urls.py create mode 100644 mensaviewer/views.py create mode 100644 static/base.css create mode 100644 webprog/__init__.py create mode 100644 webprog/asgi.py create mode 100644 webprog/settings.py create mode 100644 webprog/urls.py create mode 100644 webprog/wsgi.py diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..68dc517 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webprog.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/mensaviewer/__init__.py b/mensaviewer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mensaviewer/admin.py b/mensaviewer/admin.py new file mode 100644 index 0000000..4989254 --- /dev/null +++ b/mensaviewer/admin.py @@ -0,0 +1,23 @@ +from django.contrib import admin + +from .models import * + + +@admin.register(Menu) +class MenuAdmin(admin.ModelAdmin): + pass + + +@admin.register(Comment) +class CommentAdmin(admin.ModelAdmin): + pass + + +@admin.register(Location) +class LocationAdmin(admin.ModelAdmin): + pass + + +@admin.register(Day) +class DayAdmin(admin.ModelAdmin): + pass diff --git a/mensaviewer/apps.py b/mensaviewer/apps.py new file mode 100644 index 0000000..6a1cb7e --- /dev/null +++ b/mensaviewer/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MensaviewerConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'mensaviewer' diff --git a/mensaviewer/data.py b/mensaviewer/data.py new file mode 100644 index 0000000..aefcf23 --- /dev/null +++ b/mensaviewer/data.py @@ -0,0 +1,16 @@ +STATUS_VALUES = ['Student', 'Employee', 'Guest'] +TYPES = { + 'vn': 'Vegan', + 've': 'Vegetarisch', + 'BIO': 'Bio', + 'IN': 'International', + 'MV': 'MensaVital', + 'S': 'Schwein', + 'R': 'Rind', + 'G': 'Geflügel', + 'L': 'Lamm', + 'AGS': 'Artgerechtes Schwein', + 'AGR': 'Artgerechtes Rind', + 'AGG': 'Artgerechtes Geflügel', + 'AGL': 'Artgerechtes Lamm', +} diff --git a/mensaviewer/forms.py b/mensaviewer/forms.py new file mode 100644 index 0000000..cab3579 --- /dev/null +++ b/mensaviewer/forms.py @@ -0,0 +1,11 @@ +from django import forms + +from .models import * + +from datetime import date + + +class CommentForm(forms.ModelForm): + class Meta: + model = Comment + fields = '__all__' diff --git a/mensaviewer/helpers.py b/mensaviewer/helpers.py new file mode 100644 index 0000000..f1e0569 --- /dev/null +++ b/mensaviewer/helpers.py @@ -0,0 +1,142 @@ +from django.shortcuts import get_object_or_404 +from django.core.exceptions import ObjectDoesNotExist +from django.utils.dateparse import parse_date + +from .models import * + +from collections import OrderedDict + +import datetime +import requests + + +example_json = [ +{"day": "2022-12-19", "menus": [{"art": "Mensa", "name": "Spaghetti Carbonara", "price": "2,35 € / 4,15 € / 4,85 €", "allergens": ["GlW", "Mi"], "types": ["S", "IN"]}, {"art": "Mensa", "name": "Currywurst VEGAN Hot Pot(t) Karamellisierte Balsamico Zwiebeln Kartoffelspalten", "price": "4,05 € / 5,85 € / 6,55 €", "allergens": ["Sf", "Sl", "So", "Sw"], "types": ["ve", "vn"]}, {"art": "Mensa", "name": "Schupfnudeln, Schmorgemüse, Sojasoße", "price": "3,95 € / 5,75 € / 6,45 €", "allergens": ["GlW", "Se", "So"], "types": ["ve", "vn"]}, {"art": "Cafeteria", "name": "Currywurst Pommes Frites", "price": "4,70 € / 4,70 € / 4,70 €", "allergens": ["Sf"], "types": ["AGS"]}, {"art": "Cafeteria", "name": "Hähnchenschnitzel, Knuspermantel", "price": "2,95 € / 2,95 € / 2,95 €", "allergens": ["GlW", "GlG"], "types": ["G"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Erbsen, Karotten, Gouda", "price": "3,60 € / 3,60 € / 3,60 €", "allergens": ["Ei", "Mi"], "types": ["ve"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Hähnchenbruststreifen, Gouda", "price": "3,95 € / 3,95 € / 3,95 €", "allergens": ["Ei", "Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Ofenkartoffel mit Sour Creme [Bio]", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Mi"], "types": ["ve", "BIO"]}, {"art": "Cafeteria", "name": "OfenkartoffelTomaten- Zwiebel- Marmelade", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Sf", "Sw"], "types": ["ve", "vn"]}, {"art": "Cafeteria", "name": "Ofenkartoffel Hähnchenstreifen", "price": "3,80 € / 3,80 € / 3,80 €", "allergens": ["Mi"], "types": ["G"]}]}, +{"day": "2022-12-20", "menus": [{"art": "Mensa", "name": "Linseneintopf Baguettebrot", "price": "2,35 € / 4,15 € / 4,85 €", "allergens": ["Sl", "Sw", "GlW"], "types": ["ve", "vn"]}, {"art": "Mensa", "name": "Phat Krapao Würzige Thai Soja Bolognese, Ingwer, Basilikum, Koriander, Limettenblätter, Mienudeln", "price": "2,80 € / 4,60 € / 5,30 €", "allergens": ["GlW", "GlG", "So"], "types": ["IN", "ve", "vn"]}, {"art": "Mensa", "name": "Bockwurst zum Eintopf", "price": "1,00 € / 1,10 € / 1,20 €", "allergens": [], "types": ["S"]}, {"art": "Mensa", "name": "Filipino Beef Caldereta Basmatireis", "price": "3,50 € / 5,30 € / 6,00 €", "allergens": ["Fi", "GlW", "Mi", "Sf", "So"], "types": ["G", "R", "IN"]}, {"art": "Cafeteria", "name": "Hähnchenschnitzel, Knuspermantel", "price": "2,95 € / 2,95 € / 2,95 €", "allergens": ["GlW", "GlG"], "types": ["G"]}, {"art": "Cafeteria", "name": "Currywurst Pommes Frites", "price": "4,70 € / 4,70 € / 4,70 €", "allergens": ["Sf"], "types": ["AGS"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Hähnchenbruststreifen, Gouda", "price": "3,95 € / 3,95 € / 3,95 €", "allergens": ["Ei", "Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Erbsen, Karotten, Gouda", "price": "3,60 € / 3,60 € / 3,60 €", "allergens": ["Ei", "Mi"], "types": ["ve"]}, {"art": "Cafeteria", "name": "OfenkartoffelTomaten- Zwiebel- Marmelade", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Sf", "Sw"], "types": ["ve", "vn"]}, {"art": "Cafeteria", "name": "Ofenkartoffel mit Sour Creme [Bio]", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Mi"], "types": ["ve", "BIO"]}, {"art": "Cafeteria", "name": "Ofenkartoffel Hähnchenstreifen", "price": "3,80 € / 3,80 € / 3,80 €", "allergens": ["Mi"], "types": ["G"]}]}, +{"day": "2022-12-21", "menus": [{"art": "Mensa", "name": "Currywurst Hot Pot(t) Kartoffelspalten", "price": "3,90 € / 5,70 € / 6,40 €", "allergens": ["Sf", "Sl", "GlW"], "types": ["AGS"]}, {"art": "Mensa", "name": "Pasta, Kürbis- Ricotta- Soße, Walnüsse", "price": "2,35 € / 4,15 € / 4,85 €", "allergens": ["GlW", "Mi", "NW"], "types": ["ve"]}, {"art": "Mensa", "name": "Rindfleischcurry, Kokos, Karotten, Koriander Basmatireis", "price": "4,10 € / 5,90 € / 6,60 €", "allergens": ["GlW", "Mi", "Sf", "So"], "types": ["R"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Erbsen, Karotten, Gouda", "price": "3,60 € / 3,60 € / 3,60 €", "allergens": ["Ei", "Mi"], "types": ["ve"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Hähnchenbruststreifen, Gouda", "price": "3,95 € / 3,95 € / 3,95 €", "allergens": ["Ei", "Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Ofenkartoffel Hähnchenstreifen", "price": "3,80 € / 3,80 € / 3,80 €", "allergens": ["Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Ofenkartoffel mit Sour Creme [Bio]", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Mi"], "types": ["ve", "BIO"]}, {"art": "Cafeteria", "name": "OfenkartoffelTomaten- Zwiebel- Marmelade", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Sf", "Sw"], "types": ["ve", "vn"]}]}, +{"day": "2022-12-22", "menus": [{"art": "Mensa", "name": "Spaghetti Carbonara", "price": "2,35 € / 4,15 € / 4,85 €", "allergens": ["Ei", "GlW", "Mi"], "types": ["S", "IN"]}, {"art": "Mensa", "name": "Tortellini, Kicherbsen, Spitzkohl, Cashewkerne und Rosmarin", "price": "3,50 € / 5,30 € / 6,00 €", "allergens": ["GlW", "NC"], "types": ["ve", "vn"]}, {"art": "Mensa", "name": "Bockwurst zum Eintopf", "price": "", "allergens": [], "types": ["S"]}, {"art": "Mensa", "name": "Vegetarisches Schnitzel, mediterran gefüllt Kartoffelpüree Gurkensalat", "price": "3,65 € / 5,45 € / 6,15 €", "allergens": ["Ei", "GlW", "GlH", "Mi"], "types": ["ve"]}, {"art": "Mensa", "name": "Linseneintopf", "price": "2,00 € / 3,80 € / 4,50 €", "allergens": ["Sl", "Sw"], "types": ["ve", "vn"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Hähnchenbruststreifen, Gouda", "price": "3,95 € / 3,95 € / 3,95 €", "allergens": ["Ei", "Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Erbsen, Karotten, Gouda", "price": "3,60 € / 3,60 € / 3,60 €", "allergens": ["Ei", "Mi"], "types": ["ve"]}, {"art": "Cafeteria", "name": "Ofenkartoffel mit Sour Creme [Bio]", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Mi"], "types": ["ve", "BIO"]}, {"art": "Cafeteria", "name": "Ofenkartoffel Hähnchenstreifen", "price": "3,80 € / 3,80 € / 3,80 €", "allergens": ["Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "OfenkartoffelTomaten- Zwiebel- Marmelade", "price": "", "allergens": ["Sf", "Sw"], "types": ["ve", "vn"]}]}, +{"day": "2022-12-23", "menus": [{"art": "Mensa", "name": "Spaghetti Carbonara", "price": "2,35 € / 4,15 € / 4,85 €", "allergens": ["Ei", "GlW", "Mi"], "types": ["S", "IN"]}, {"art": "Mensa", "name": "Tortellini, Kicherbsen, Spitzkohl, Cashewkerne und Rosmarin", "price": "3,50 € / 5,30 € / 6,00 €", "allergens": ["GlW", "NC"], "types": ["ve", "vn"]}, {"art": "Mensa", "name": "Bockwurst zum Eintopf", "price": "", "allergens": [], "types": ["S"]}, {"art": "Mensa", "name": "Vegetarisches Schnitzel, mediterran gefüllt Kartoffelpüree Gurkensalat", "price": "3,65 € / 5,45 € / 6,15 €", "allergens": ["Ei", "GlW", "GlH", "Mi"], "types": ["ve"]}, {"art": "Mensa", "name": "Linseneintopf", "price": "2,00 € / 3,80 € / 4,50 €", "allergens": ["Sl", "Sw"], "types": ["ve", "vn"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Hähnchenbruststreifen, Gouda", "price": "3,95 € / 3,95 € / 3,95 €", "allergens": ["Ei", "Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "Kartoffelgratin, Erbsen, Karotten, Gouda", "price": "3,60 € / 3,60 € / 3,60 €", "allergens": ["Ei", "Mi"], "types": ["ve"]}, {"art": "Cafeteria", "name": "Ofenkartoffel mit Sour Creme [Bio]", "price": "3,30 € / 3,30 € / 3,30 €", "allergens": ["Mi"], "types": ["ve", "BIO"]}, {"art": "Cafeteria", "name": "Ofenkartoffel Hähnchenstreifen", "price": "3,80 € / 3,80 € / 3,80 €", "allergens": ["Mi"], "types": ["G"]}, {"art": "Cafeteria", "name": "OfenkartoffelTomaten- Zwiebel- Marmelade", "price": "", "allergens": ["Sf", "Sw"], "types": ["ve", "vn"]}]}] + + +def load_data(locations, checked_types, status): + current_week = datetime.date.today().isocalendar().week + days = Day.objects.filter(date__week=current_week) + + for location in locations: + menus = Menu.objects.filter(days__in=days, locations=location) + if not menus.exists(): + fetched_data = fetch(location.mensa_id) + store(fetched_data, location) + + data = formatted_menu_data(locations, checked_types, status) + return data + + +def formatted_menu_data(locations, checked_types, status): + current_week = datetime.date.today().isocalendar().week + days = Day.objects.filter(date__week=current_week) + + formatted_data = {} + + for day in days: + formatted_data[str(day.date)] = [] + + for day in days: + for location in locations: + menus = Menu.objects.filter(days=day, locations=location) + for menu in menus: + + + # AND or OR filter ??? + if set(checked_types).issubset(set(menu.types)): # <-- AND + + + + formatted_data[str(day.date)].append({ + 'art': menu.art, + 'name': menu.name, + 'price': menu.price if status is None else menu.get_price[status], + 'allergens': menu.get_allergens, + 'types': menu.get_types, + 'likes': menu.likes, + 'location': location.name, + 'pk': menu.pk, + }) + return formatted_data + + +def store(data, location): + for day_json in data: + date_string= day_json['day'] + menus_json = day_json['menus'] + + date = parse_date(date_string) + + if not Day.objects.filter(date=date).exists(): + Day(date=date).save() + + day = Day.objects.get(date=date) + + for menu_json in menus_json: + art = menu_json['art'] + name = menu_json['name'] + price = menu_json['price'] or "0,00€ / 0,00€ / 0,00€" + allergens = menu_json['allergens'] + types = menu_json['types'] + + menu_exists = Menu.objects.filter(art=art, name=name, price=price, allergens=allergens, types=types).exists() + + if not menu_exists: + Menu(art=art, name=name, price=price, allergens=allergens, types=types).save() + + menu = Menu.objects.get(art=art, name=name, price=price, allergens=allergens, types=types) + menu.locations.add(location) + menu.days.add(day) + menu.save() + + +def fetch(mensa_id: int): + res = requests.get('https://mensa.fly.dev/' + str(mensa_id)) + if res.status_code != 200: + raise Exception('request failed') + return res.json() + + +def models_from_json(mensa_id: int): + for day_json in fetch_menus(mensa_id): + day_date = datetime.datetime.strptime(day_json['day'], '%Y-%m-%d').date() + + if not Day.objects.filter(mensa_id=mensa_id, date__contains=day_date): + # create new day model ONLY if it does not yet exist for the given + # day_date(s) and mensa_id. + + Day(mensa_id=mensa_id, date=day_date).save() + day = Day.objects.get(mensa_id=mensa_id, date=day_date) + + for menu_json in day_json['menus']: + # if meal already exists, simply add day to related menus. + # otherwise, build new meal model from json with the specified menu + # as the first related menu. + + if not Menu.objects.filter(name=menu_json['name']): + Menu.from_json(menu_json, day).save() + + day.menus.add(Menu.objects.get(name=menu_json['name'])) + + +def days_as_json(mensa_ids: list, types_filter: list, price_filter: str): + cw = datetime.date.today().isocalendar().week + dates = list(dict.fromkeys([day.date for day in Day.objects.filter(date__week=cw)])) + + days_list = [] + for date in dates: + day_json = { 'day': date, 'menus': [] } + for mensa_id in mensa_ids: + try: + day = Day.objects.get(mensa_id=mensa_id, date=date) + for menu in Menu.objects.filter(day=day, related_types__in=Type.objects.filter(type__in=types_filter) if types_filter else Type.objects.all()).distinct(): + day_json['menus'].append({ 'menu': menu, 'mensa_id': mensa_id }) + except ObjectDoesNotExist: + pass + days_list.append(day_json) + return days_list diff --git a/mensaviewer/migrations/0001_initial.py b/mensaviewer/migrations/0001_initial.py new file mode 100644 index 0000000..17b6426 --- /dev/null +++ b/mensaviewer/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 4.1.4 on 2022-12-25 15:48 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Menu', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('mensa_id', models.IntegerField()), + ('date', models.CharField(max_length=10)), + ], + ), + migrations.CreateModel( + name='Meal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=144)), + ('type', models.CharField(max_length=144)), + ('allergens', models.CharField(max_length=144)), + ('tags', models.CharField(max_length=144)), + ('likes', models.IntegerField(default=0)), + ('dislikes', models.IntegerField(default=0)), + ('price_student', models.FloatField(max_length=8)), + ('price_employee', models.FloatField(max_length=8)), + ('price_guest', models.FloatField(max_length=8)), + ('related_menus', models.ManyToManyField(to='mensaviewer.menu')), + ], + ), + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('username', models.CharField(default='anon', max_length=144)), + ('comment', models.CharField(max_length=720)), + ('related_meal', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='mensaviewer.meal')), + ], + ), + ] diff --git a/mensaviewer/migrations/0002_alter_menu_date.py b/mensaviewer/migrations/0002_alter_menu_date.py new file mode 100644 index 0000000..c0c3094 --- /dev/null +++ b/mensaviewer/migrations/0002_alter_menu_date.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2022-12-26 15:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='menu', + name='date', + field=models.DateField(), + ), + ] diff --git a/mensaviewer/migrations/0003_alter_menu_date.py b/mensaviewer/migrations/0003_alter_menu_date.py new file mode 100644 index 0000000..7ffaf64 --- /dev/null +++ b/mensaviewer/migrations/0003_alter_menu_date.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2022-12-26 15:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0002_alter_menu_date'), + ] + + operations = [ + migrations.AlterField( + model_name='menu', + name='date', + field=models.DateField(max_length=10), + ), + ] diff --git a/mensaviewer/migrations/0004_day_remove_menu_date_remove_menu_mensa_id_and_more.py b/mensaviewer/migrations/0004_day_remove_menu_date_remove_menu_mensa_id_and_more.py new file mode 100644 index 0000000..1073589 --- /dev/null +++ b/mensaviewer/migrations/0004_day_remove_menu_date_remove_menu_mensa_id_and_more.py @@ -0,0 +1,88 @@ +# Generated by Django 4.1.4 on 2022-12-26 16:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0003_alter_menu_date'), + ] + + operations = [ + migrations.CreateModel( + name='Day', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('mensa_id', models.IntegerField()), + ('date', models.DateField(max_length=10)), + ], + ), + migrations.RemoveField( + model_name='menu', + name='date', + ), + migrations.RemoveField( + model_name='menu', + name='mensa_id', + ), + migrations.AddField( + model_name='menu', + name='allergens', + field=models.CharField(blank=True, max_length=144, null=True), + ), + migrations.AddField( + model_name='menu', + name='dislikes', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='menu', + name='likes', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='menu', + name='name', + field=models.CharField(blank=True, max_length=144, null=True), + ), + migrations.AddField( + model_name='menu', + name='price_employee', + field=models.FloatField(default=0, max_length=8), + ), + migrations.AddField( + model_name='menu', + name='price_guest', + field=models.FloatField(default=0, max_length=8), + ), + migrations.AddField( + model_name='menu', + name='price_student', + field=models.FloatField(default=0, max_length=8), + ), + migrations.AddField( + model_name='menu', + name='tags', + field=models.CharField(blank=True, max_length=144, null=True), + ), + migrations.AddField( + model_name='menu', + name='type', + field=models.CharField(blank=True, max_length=144, null=True), + ), + migrations.AlterField( + model_name='comment', + name='related_meal', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='mensaviewer.menu'), + ), + migrations.DeleteModel( + name='Meal', + ), + migrations.AddField( + model_name='menu', + name='related_menus', + field=models.ManyToManyField(to='mensaviewer.day'), + ), + ] diff --git a/mensaviewer/migrations/0005_rename_related_menus_menu_related_days.py b/mensaviewer/migrations/0005_rename_related_menus_menu_related_days.py new file mode 100644 index 0000000..2b351bd --- /dev/null +++ b/mensaviewer/migrations/0005_rename_related_menus_menu_related_days.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2022-12-26 21:04 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0004_day_remove_menu_date_remove_menu_mensa_id_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='menu', + old_name='related_menus', + new_name='related_days', + ), + ] diff --git a/mensaviewer/migrations/0006_allergen_tag_remove_menu_allergens_remove_menu_tags_and_more.py b/mensaviewer/migrations/0006_allergen_tag_remove_menu_allergens_remove_menu_tags_and_more.py new file mode 100644 index 0000000..41d2c6c --- /dev/null +++ b/mensaviewer/migrations/0006_allergen_tag_remove_menu_allergens_remove_menu_tags_and_more.py @@ -0,0 +1,50 @@ +# Generated by Django 4.1.4 on 2022-12-27 00:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0005_rename_related_menus_menu_related_days'), + ] + + operations = [ + migrations.CreateModel( + name='Allergen', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('allergen', models.CharField(blank=True, max_length=16, null=True)), + ], + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('tag', models.CharField(blank=True, max_length=16, null=True)), + ], + ), + migrations.RemoveField( + model_name='menu', + name='allergens', + ), + migrations.RemoveField( + model_name='menu', + name='tags', + ), + migrations.AlterField( + model_name='menu', + name='related_days', + field=models.ManyToManyField(related_name='menus', to='mensaviewer.day'), + ), + migrations.AddField( + model_name='menu', + name='related_allergens', + field=models.ManyToManyField(related_name='menus', to='mensaviewer.allergen'), + ), + migrations.AddField( + model_name='menu', + name='related_tags', + field=models.ManyToManyField(related_name='menus', to='mensaviewer.tag'), + ), + ] diff --git a/mensaviewer/migrations/0007_allergen_name_tag_name.py b/mensaviewer/migrations/0007_allergen_name_tag_name.py new file mode 100644 index 0000000..08f6493 --- /dev/null +++ b/mensaviewer/migrations/0007_allergen_name_tag_name.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.4 on 2023-01-02 02:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0006_allergen_tag_remove_menu_allergens_remove_menu_tags_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='allergen', + name='name', + field=models.CharField(blank=True, max_length=144, null=True), + ), + migrations.AddField( + model_name='tag', + name='name', + field=models.CharField(blank=True, max_length=144, null=True), + ), + ] diff --git a/mensaviewer/migrations/0008_rename_tag_type_and_more.py b/mensaviewer/migrations/0008_rename_tag_type_and_more.py new file mode 100644 index 0000000..d5fa164 --- /dev/null +++ b/mensaviewer/migrations/0008_rename_tag_type_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.1.4 on 2023-01-02 17:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0007_allergen_name_tag_name'), + ] + + operations = [ + migrations.RenameModel( + old_name='Tag', + new_name='Type', + ), + migrations.RenameField( + model_name='menu', + old_name='related_tags', + new_name='related_types', + ), + migrations.RenameField( + model_name='type', + old_name='tag', + new_name='type', + ), + ] diff --git a/mensaviewer/migrations/0009_rename_type_menu_art.py b/mensaviewer/migrations/0009_rename_type_menu_art.py new file mode 100644 index 0000000..f232b93 --- /dev/null +++ b/mensaviewer/migrations/0009_rename_type_menu_art.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2023-01-03 02:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0008_rename_tag_type_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='menu', + old_name='type', + new_name='art', + ), + ] diff --git a/mensaviewer/migrations/0010_remove_menu_related_days_day_menus_alter_day_date_and_more.py b/mensaviewer/migrations/0010_remove_menu_related_days_day_menus_alter_day_date_and_more.py new file mode 100644 index 0000000..a6285f9 --- /dev/null +++ b/mensaviewer/migrations/0010_remove_menu_related_days_day_menus_alter_day_date_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 4.1.4 on 2023-01-03 23:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0009_rename_type_menu_art'), + ] + + operations = [ + migrations.RemoveField( + model_name='menu', + name='related_days', + ), + migrations.AddField( + model_name='day', + name='menus', + field=models.ManyToManyField(related_name='day', to='mensaviewer.menu'), + ), + migrations.AlterField( + model_name='day', + name='date', + field=models.DateField(max_length=64), + ), + migrations.AlterField( + model_name='menu', + name='related_allergens', + field=models.ManyToManyField(related_name='menu', to='mensaviewer.allergen'), + ), + migrations.AlterField( + model_name='menu', + name='related_types', + field=models.ManyToManyField(related_name='menu', to='mensaviewer.type'), + ), + ] diff --git a/mensaviewer/migrations/0011_rename_related_meal_comment_related_menu.py b/mensaviewer/migrations/0011_rename_related_meal_comment_related_menu.py new file mode 100644 index 0000000..f8a6f36 --- /dev/null +++ b/mensaviewer/migrations/0011_rename_related_meal_comment_related_menu.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2023-01-04 03:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0010_remove_menu_related_days_day_menus_alter_day_date_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='comment', + old_name='related_meal', + new_name='related_menu', + ), + ] diff --git a/mensaviewer/migrations/0012_location_remove_day_menus_remove_menu_dislikes_and_more.py b/mensaviewer/migrations/0012_location_remove_day_menus_remove_menu_dislikes_and_more.py new file mode 100644 index 0000000..02d8036 --- /dev/null +++ b/mensaviewer/migrations/0012_location_remove_day_menus_remove_menu_dislikes_and_more.py @@ -0,0 +1,84 @@ +# Generated by Django 4.1.4 on 2023-01-04 16:57 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0011_rename_related_meal_comment_related_menu'), + ] + + operations = [ + migrations.CreateModel( + name='Location', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, max_length=144, null=True)), + ('mensa_id', models.CharField(blank=True, max_length=2, null=True)), + ], + ), + migrations.RemoveField( + model_name='day', + name='menus', + ), + migrations.RemoveField( + model_name='menu', + name='dislikes', + ), + migrations.RemoveField( + model_name='menu', + name='price_employee', + ), + migrations.RemoveField( + model_name='menu', + name='price_guest', + ), + migrations.RemoveField( + model_name='menu', + name='price_student', + ), + migrations.RemoveField( + model_name='menu', + name='related_allergens', + ), + migrations.RemoveField( + model_name='menu', + name='related_types', + ), + migrations.AddField( + model_name='menu', + name='allergens', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='menu', + name='day', + field=models.DateField(blank=True, null=True), + ), + migrations.AddField( + model_name='menu', + name='types', + field=models.JSONField(blank=True, null=True), + ), + migrations.AlterField( + model_name='comment', + name='related_menu', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mensaviewer.menu'), + ), + migrations.DeleteModel( + name='Allergen', + ), + migrations.DeleteModel( + name='Day', + ), + migrations.DeleteModel( + name='Type', + ), + migrations.AddField( + model_name='menu', + name='location', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='mensaviewer.location'), + ), + ] diff --git a/mensaviewer/migrations/0013_menu_price.py b/mensaviewer/migrations/0013_menu_price.py new file mode 100644 index 0000000..7de9fa5 --- /dev/null +++ b/mensaviewer/migrations/0013_menu_price.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2023-01-04 22:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0012_location_remove_day_menus_remove_menu_dislikes_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='menu', + name='price', + field=models.CharField(blank=True, max_length=144, null=True), + ), + ] diff --git a/mensaviewer/migrations/0014_day_remove_menu_day_remove_menu_location_and_more.py b/mensaviewer/migrations/0014_day_remove_menu_day_remove_menu_location_and_more.py new file mode 100644 index 0000000..5879d1a --- /dev/null +++ b/mensaviewer/migrations/0014_day_remove_menu_day_remove_menu_location_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 4.1.4 on 2023-01-04 23:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0013_menu_price'), + ] + + operations = [ + migrations.CreateModel( + name='Day', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField(blank=True, null=True)), + ], + ), + migrations.RemoveField( + model_name='menu', + name='day', + ), + migrations.RemoveField( + model_name='menu', + name='location', + ), + migrations.AddField( + model_name='menu', + name='locations', + field=models.ManyToManyField(to='mensaviewer.location'), + ), + migrations.AddField( + model_name='menu', + name='days', + field=models.ManyToManyField(to='mensaviewer.day'), + ), + ] diff --git a/mensaviewer/migrations/0015_comment_timestamp.py b/mensaviewer/migrations/0015_comment_timestamp.py new file mode 100644 index 0000000..d670106 --- /dev/null +++ b/mensaviewer/migrations/0015_comment_timestamp.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.4 on 2023-01-05 00:43 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensaviewer', '0014_day_remove_menu_day_remove_menu_location_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='comment', + name='timestamp', + field=models.DateTimeField(blank=True, default=django.utils.timezone.now), + ), + ] diff --git a/mensaviewer/migrations/__init__.py b/mensaviewer/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mensaviewer/models.py b/mensaviewer/models.py new file mode 100644 index 0000000..a5679c1 --- /dev/null +++ b/mensaviewer/models.py @@ -0,0 +1,60 @@ +from django.db import models +from django.utils.timezone import now + +from .data import TYPES + + +class Day(models.Model): + date = models.DateField(null=True, blank=True) + + def __str__(self): + return str(self.date) + + +class Location(models.Model): + name = models.CharField(max_length=144, null=True, blank=True) + mensa_id = models.CharField(max_length=2, null=True, blank=True) + + def __str__(self): + return self.name + + +class Menu(models.Model): + art = models.CharField(max_length=144, null=True, blank=True) + name = models.CharField(max_length=144, null=True, blank=True) + price = models.CharField(max_length=144, null=True, blank=True) + allergens = models.JSONField(null=True, blank=True) + types = models.JSONField(null=True, blank=True) + likes = models.IntegerField(default=0) + locations = models.ManyToManyField(Location) + days = models.ManyToManyField(Day) + + def __str__(self): + return self.name + + @property + def get_price(self): + return { + 'Student': self.price.split(' / ')[0] or 0, + 'Employee': self.price.split(' / ')[1] or 0, + 'Guest': self.price.split(' / ')[2] or 0, + } + + @property + def get_types(self): + return ', '.join([TYPES[type] for type in self.types]) + + @property + def get_allergens(self): + return ', '.join([allergen for allergen in self.allergens]) + + @property + def comments(self): + return [comment for comment in Comment.objects.filter(related_menu=self)] + + +class Comment(models.Model): + related_menu = models.ForeignKey(Menu, on_delete=models.CASCADE) + timestamp = models.DateTimeField(default=now, blank=True) + username = models.CharField(max_length=144, default='anon') + comment = models.CharField(max_length=720) diff --git a/mensaviewer/templates/base.html b/mensaviewer/templates/base.html new file mode 100644 index 0000000..e8f51df --- /dev/null +++ b/mensaviewer/templates/base.html @@ -0,0 +1,23 @@ +{% load static %} + + + + + + + Mensaviewer | {% block title %}Home{%endblock%} + + +
+

Header Title

+
+ +
+ {% block content %} + {% endblock %} +
+ + diff --git a/mensaviewer/templates/comment.html b/mensaviewer/templates/comment.html new file mode 100644 index 0000000..ac0e7bd --- /dev/null +++ b/mensaviewer/templates/comment.html @@ -0,0 +1,10 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ {% csrf_token %} + {{ form }} + +
+{% endblock %} diff --git a/mensaviewer/templates/create_location.html b/mensaviewer/templates/create_location.html new file mode 100644 index 0000000..481904b --- /dev/null +++ b/mensaviewer/templates/create_location.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ {% csrf_token %} + {{ form }} + +
+ +{% endblock %} diff --git a/mensaviewer/templates/flensburg.html b/mensaviewer/templates/flensburg.html new file mode 100644 index 0000000..1da86c9 --- /dev/null +++ b/mensaviewer/templates/flensburg.html @@ -0,0 +1,69 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ +
+ {% for name, id in types %} + + {% endfor %} +
+
+ {% for status_value in status_values %} + + {% endfor %} +
+
+ {% for location in locations %} + + {% endfor %} +
+ New Location + +
+ +
+ {% for day, menus in menu_data.items %} +
+

{{ day }}

+ + {% for menu in menus %} + + {% endfor %} + + + +
+ {% endfor %} +
+ + +{% endblock %} diff --git a/mensaviewer/templates/menu_detail.html b/mensaviewer/templates/menu_detail.html new file mode 100644 index 0000000..de9acdc --- /dev/null +++ b/mensaviewer/templates/menu_detail.html @@ -0,0 +1,27 @@ +{% extends 'base.html' %} + +{% block content %} + + + +{% endblock %} diff --git a/mensaviewer/tests.py b/mensaviewer/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/mensaviewer/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/mensaviewer/urls.py b/mensaviewer/urls.py new file mode 100644 index 0000000..825038f --- /dev/null +++ b/mensaviewer/urls.py @@ -0,0 +1,12 @@ +from django.urls import path +from . import views + +app_name = 'mensaviewer' +urlpatterns = [ + path('', views.home, name='home'), + path('menu//', views.MenuDetailView.as_view(), name='menu_detail'), + path('menu//like/', views.like, name='like'), + path('menu//dislike/', views.dislike, name='dislike'), + path('menu//comment/', views.CommentCreateView.as_view(), name='comment'), + path('location/create/', views.LocationCreateView.as_view(), name='location_create') +] diff --git a/mensaviewer/views.py b/mensaviewer/views.py new file mode 100644 index 0000000..d11481e --- /dev/null +++ b/mensaviewer/views.py @@ -0,0 +1,75 @@ +from django.views.generic import DetailView +from django.views.generic.edit import CreateView +from django.shortcuts import render, redirect, reverse + +from .models import * +from .helpers import * +from .forms import * +from .data import * + + +def home(request): + filter_query = request.COOKIES.get('filter_query', '') + if len(request.GET.getlist('filterform')) == 0 and filter_query != '': + return redirect(reverse('mensaviewer:home') + '?' + filter_query) + + selected_location_ids = request.GET.getlist('location') + checked_types = request.GET.getlist('type') + status = request.GET.get('status') + selected_locations = Location.objects.filter(mensa_id__in=selected_location_ids) + + context = { + 'types': [(TYPES[type], type) for type in TYPES], + 'checked_types': checked_types, + 'status_values': STATUS_VALUES, + 'status': status, + 'locations': Location.objects.all(), + 'selected_locations': selected_location_ids, + 'menu_data': load_data(selected_locations, checked_types, status), + } + + response = render(request, "flensburg.html", context) + response.set_cookie('filter_query', request.GET.urlencode()) + return response + + +def like(request, pk): + if request.method == 'GET': + menu = Menu.objects.get(pk=pk) + menu.likes += 1 + menu.save() + return redirect(reverse('mensaviewer:home') + '?' + request.GET.get('next')) + + +def dislike(request, pk): + if request.method == 'GET': + menu = Menu.objects.get(pk=pk) + menu.likes -= 1 + menu.save() + return redirect(reverse('mensaviewer:home') + '?' + request.GET.get('next')) + + +class MenuDetailView(DetailView): + model = Menu + template_name = "menu_detail.html" + queryset = Menu.objects.all() + + +class LocationCreateView(CreateView): + model = Location + fields = '__all__' + template_name = "create_location.html" + success_url = "/" + + +class CommentCreateView(CreateView): + model = Comment + fields = ['username', 'comment'] + template_name = "comment.html" + success_url = '/menu/{pk}/' + + def form_valid(self, form): + self.menu = get_object_or_404(Menu, pk=self.kwargs['pk']) + form.instance.menu = self.menu + print(self.menu) + return super().form_valid(form) diff --git a/static/base.css b/static/base.css new file mode 100644 index 0000000..fb859d9 --- /dev/null +++ b/static/base.css @@ -0,0 +1,33 @@ +* { + font-family: monospace; + box-sizing: border-box; + outline: 1px solid green; + background-color: rgba(16, 16, 16, 0.1) +} + +body { + margin: 0; +} + +.container { + display: flex; + flex-flow: row wrap; +} + +.column { + flex: 1; + flex-flow: column; +} + +.menu { + display: flex; + flex-direction: column; +} + +.a-mensa { + background-color: rgba(16, 64, 16, 0.2); +} + +.b-mensa { + background-color: rgba(16, 16, 64, 0.2); +} diff --git a/webprog/__init__.py b/webprog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/webprog/asgi.py b/webprog/asgi.py new file mode 100644 index 0000000..efea017 --- /dev/null +++ b/webprog/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for webprog project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webprog.settings') + +application = get_asgi_application() diff --git a/webprog/settings.py b/webprog/settings.py new file mode 100644 index 0000000..a03a411 --- /dev/null +++ b/webprog/settings.py @@ -0,0 +1,128 @@ +""" +Django settings for webprog project. + +Generated by 'django-admin startproject' using Django 4.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-srl4kvoe3zz=@x^h6aew)s4(&4!$96g%)%ar+yfpp@4t*0oo9(' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['127.0.0.1', '192.168.178.36'] + + +# Application definition + +INSTALLED_APPS = [ + 'mensaviewer.apps.MensaviewerConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'webprog.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'webprog.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = 'static/' + +STATICFILES_DIRS = [ + BASE_DIR/"static", +] + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/webprog/urls.py b/webprog/urls.py new file mode 100644 index 0000000..c5c9b59 --- /dev/null +++ b/webprog/urls.py @@ -0,0 +1,22 @@ +"""webprog URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('mensaviewer.urls')) +] diff --git a/webprog/wsgi.py b/webprog/wsgi.py new file mode 100644 index 0000000..8d2b237 --- /dev/null +++ b/webprog/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for webprog project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webprog.settings') + +application = get_wsgi_application()