@@ -0,0 +1,4 @@ | |||
/venv/ | |||
/db.sqlite3 | |||
/playground.py | |||
/playground2.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', 'mysite.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() |
@@ -0,0 +1,16 @@ | |||
""" | |||
ASGI config for mysite 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.2/howto/deployment/asgi/ | |||
""" | |||
import os | |||
from django.core.asgi import get_asgi_application | |||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') | |||
application = get_asgi_application() |
@@ -0,0 +1,124 @@ | |||
""" | |||
Django settings for mysite project. | |||
Generated by 'django-admin startproject' using Django 4.2.6. | |||
For more information on this file, see | |||
https://docs.djangoproject.com/en/4.2/topics/settings/ | |||
For the full list of settings and their values, see | |||
https://docs.djangoproject.com/en/4.2/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.2/howto/deployment/checklist/ | |||
# SECURITY WARNING: keep the secret key used in production secret! | |||
SECRET_KEY = 'django-insecure-p0yr76f^19@hi$n)u3)w1lk35#ijlq8(@ulv#*0o8^x32b^1h&' | |||
# SECURITY WARNING: don't run with debug turned on in production! | |||
DEBUG = True | |||
ALLOWED_HOSTS = [] | |||
# Application definition | |||
INSTALLED_APPS = [ | |||
'django.contrib.admin', | |||
'django.contrib.auth', | |||
'django.contrib.contenttypes', | |||
'django.contrib.sessions', | |||
'django.contrib.messages', | |||
'django.contrib.staticfiles', | |||
'polls.apps.PollsConfig', | |||
] | |||
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 = 'mysite.urls' | |||
TEMPLATES = [ | |||
{ | |||
'BACKEND': 'django.template.backends.django.DjangoTemplates', | |||
'DIRS': [BASE_DIR / 'templates'] | |||
, | |||
'APP_DIRS': True, | |||
'OPTIONS': { | |||
'context_processors': [ | |||
'django.template.context_processors.debug', | |||
'django.template.context_processors.request', | |||
'django.contrib.auth.context_processors.auth', | |||
'django.contrib.messages.context_processors.messages', | |||
], | |||
}, | |||
}, | |||
] | |||
WSGI_APPLICATION = 'mysite.wsgi.application' | |||
# Database | |||
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases | |||
DATABASES = { | |||
'default': { | |||
'ENGINE': 'django.db.backends.sqlite3', | |||
'NAME': BASE_DIR / 'db.sqlite3', | |||
} | |||
} | |||
# Password validation | |||
# https://docs.djangoproject.com/en/4.2/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.2/topics/i18n/ | |||
LANGUAGE_CODE = 'de-de' | |||
TIME_ZONE = 'Europe/Berlin' | |||
USE_I18N = True | |||
USE_TZ = True | |||
# Static files (CSS, JavaScript, Images) | |||
# https://docs.djangoproject.com/en/4.2/howto/static-files/ | |||
STATIC_URL = 'static/' | |||
# Default primary key field type | |||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field | |||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' | |||
LOGIN_REDIRECT_URL = '/polls/' | |||
LOGOUT_REDIRECT_URL = '/polls/' | |||
@@ -0,0 +1,27 @@ | |||
""" | |||
URL configuration for mysite project. | |||
The `urlpatterns` list routes URLs to views. For more information please see: | |||
https://docs.djangoproject.com/en/4.2/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('polls/', include('polls.urls')), | |||
# ... | |||
path('admin/', admin.site.urls), | |||
path('accounts/', include('django.contrib.auth.urls')), | |||
] | |||
@@ -0,0 +1,16 @@ | |||
""" | |||
WSGI config for mysite 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.2/howto/deployment/wsgi/ | |||
""" | |||
import os | |||
from django.core.wsgi import get_wsgi_application | |||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') | |||
application = get_wsgi_application() |
@@ -0,0 +1,5 @@ | |||
from django.contrib import admin | |||
from .models import Notice | |||
admin.site.register(Notice) | |||
@@ -0,0 +1,6 @@ | |||
from django.apps import AppConfig | |||
class PollsConfig(AppConfig): | |||
default_auto_field = 'django.db.models.BigAutoField' | |||
name = 'polls' |
@@ -0,0 +1,14 @@ | |||
from django import forms | |||
import datetime | |||
class NoticeForm(forms.Form): | |||
date_formats = ['%d.%m.%Y', '%d.%m.%y'] | |||
notice_title = forms.CharField(label='Titel', max_length=80) | |||
notice_text = forms.CharField(label='Text', max_length=400) | |||
pub_start = forms.DateField(label='Von', | |||
input_formats=date_formats, | |||
initial=datetime.date.today) | |||
pub_end = forms.DateField(label='Bis', | |||
input_formats=date_formats, | |||
initial=datetime.date.today) |
@@ -0,0 +1,26 @@ | |||
# Generated by Django 4.2.6 on 2023-11-12 18:36 | |||
from django.db import migrations, models | |||
class Migration(migrations.Migration): | |||
initial = True | |||
dependencies = [ | |||
] | |||
operations = [ | |||
migrations.CreateModel( | |||
name='Notice', | |||
fields=[ | |||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |||
('notice_title', models.CharField(max_length=80)), | |||
('notice_text', models.CharField(max_length=400)), | |||
('pub_start', models.DateTimeField()), | |||
('pub_end', models.DateTimeField()), | |||
], | |||
), | |||
] | |||
@@ -0,0 +1,9 @@ | |||
from django.db import models | |||
class Notice(models.Model): | |||
notice_title = models.CharField(max_length=80) | |||
notice_text = models.CharField(max_length=400) | |||
pub_start = models.DateTimeField() | |||
pub_end = models.DateTimeField() | |||
@@ -0,0 +1,3 @@ | |||
from django.test import TestCase | |||
# Create your tests here. |
@@ -0,0 +1,10 @@ | |||
from django.urls import path | |||
from . import views | |||
urlpatterns = [ | |||
path('', views.index, name='index'), | |||
path('new', views.new, name='new'), | |||
path('delete/<int:deleteId>', views.delete, name='delete'), | |||
] | |||
@@ -0,0 +1,41 @@ | |||
from django.shortcuts import render, redirect | |||
from .models import Notice | |||
from django.utils import timezone | |||
from .forms import NoticeForm | |||
from django.contrib.auth.decorators import login_required | |||
@login_required | |||
def new(request): | |||
if request.method == 'POST': | |||
form = NoticeForm(request.POST) | |||
if form.is_valid(): | |||
notice = Notice() | |||
notice.notice_title = form.cleaned_data['notice_title'] | |||
notice.notice_text = form.cleaned_data['notice_text'] | |||
notice.pub_start = form.cleaned_data['pub_start'] | |||
notice.pub_end = form.cleaned_data['pub_end'] | |||
notice.save() | |||
return redirect('index') | |||
context = {'form': NoticeForm()} | |||
return render(request, 'polls/edit.html', context) | |||
@login_required | |||
def delete(request, deleteId=None): | |||
if deleteId is not None: | |||
try: | |||
notice = Notice.objects.get(pk=deleteId) | |||
if request.user.id == notice.user_id: | |||
notice.delete() | |||
except: | |||
pass | |||
return redirect('index') | |||
def index(request): | |||
notices = Notice.objects.all() | |||
notices = notices.filter(pub_start__lte=timezone.now()) | |||
notices = notices.filter(pub_end__gte=timezone.now()) | |||
context = {'notices': notices} | |||
return render(request, 'polls/index.html', context) | |||
@@ -0,0 +1 @@ | |||
Django>=4.2.6 |
@@ -0,0 +1,68 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta name="viewport"> | |||
<title>{% block title %} Platzhalter {% endblock %}</title> | |||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> | |||
</head> | |||
<body> | |||
<nav class="navbar navbar-expand-lg bg-body-tertiary"> | |||
<div class="container-fluid"> | |||
<a class="navbar-brand" href="#">Navbar</a> | |||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> | |||
<span class="navbar-toggler-icon"></span> | |||
</button> | |||
<div class="collapse navbar-collapse" id="navbarSupportedContent"> | |||
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> | |||
<li class="nav-item"> | |||
<a class="nav-link active" aria-current="page" href="#">Home</a> | |||
</li> | |||
<li class="nav-item"> | |||
<a class="nav-link" href="#">Link</a> | |||
</li> | |||
<li class="nav-item dropdown"> | |||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> | |||
Dropdown | |||
</a> | |||
<ul class="dropdown-menu"> | |||
<li><a class="dropdown-item" href="#">Action</a></li> | |||
<li><a class="dropdown-item" href="#">Another action</a></li> | |||
<li><hr class="dropdown-divider"></li> | |||
<li><a class="dropdown-item" href="#">Something else here</a></li> | |||
</ul> | |||
</li> | |||
<li class="nav-item"> | |||
<a class="nav-link disabled" aria-disabled="true">Disabled</a> | |||
</li> | |||
</ul> | |||
<form class="d-flex" role="search"> | |||
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> | |||
<button class="btn btn-outline-success" type="submit">Search</button> | |||
</form> | |||
</div> | |||
</div> | |||
</nav> | |||
<div class="container"> | |||
{% block content %} Platzhalter {% endblock %} | |||
{% if user.is_authenticated %} | |||
<a href="{% url 'logout' %}" class="btn btn-primary">Abmelden</a> | |||
{% endif %} | |||
{% if not user.is_authenticated %} | |||
<a href="{% url 'login' %}" class="btn btn-primary">Anmelden</a> | |||
{% endif %} | |||
</div> | |||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> | |||
</body> | |||
</html> | |||
@@ -0,0 +1,18 @@ | |||
{% extends "base.html" %} | |||
{% block title %}Edit{% endblock %} | |||
{% block content %} | |||
<h1>Neue Nachricht</h1> | |||
<form method="POST"> | |||
{% csrf_token %} | |||
{{ form.as_p }} | |||
<input class="btn btn-primary" | |||
type="submit" | |||
value="Speichern"> | |||
</form> | |||
{% endblock %} | |||
@@ -0,0 +1,38 @@ | |||
{% extends "base.html" %} | |||
{% block title %}News{% endblock %} | |||
{% block content %} | |||
<div class="jumbotron"> | |||
<h1 class="display-4">News</h1> | |||
</div> | |||
{% for notice in notices %} | |||
<hr> | |||
<h3>{{ notice.notice_title }}</h3> | |||
<p>{{ notice.notice_text }}</p> | |||
{% if user.is_staff %} | |||
<p> | |||
<a href="{% url 'delete' deleteId=notice.id %}" | |||
class="btn btn-danger"> | |||
Meldung löschen | |||
</a> | |||
</p> | |||
{% endif %} | |||
{% endfor %} | |||
<hr> | |||
<p> | |||
<a href="{% url 'new' %}" | |||
class="btn btn-primary"> | |||
Neue Meldung erstellen | |||
</a> | |||
</p> | |||
{% endblock %} | |||
@@ -0,0 +1,40 @@ | |||
{% extends "base.html" %} | |||
{% block title %}Anmeldung{% endblock %} | |||
{% block content %} | |||
{% if form.errors %} | |||
<p>Benutzername oder Passwort falsch.</p> | |||
{% endif %} | |||
{% if next %} | |||
{% if user.is_authenticated %} | |||
<p>Sie haben nicht die hierfür notwendige Berechtigung.</p> | |||
{% else %} | |||
<p>Bitte melden Sie sich an.</p> | |||
{% endif %} | |||
{% endif %} | |||
<form method="post" action="{% url 'login' %}"> | |||
{% csrf_token %} | |||
<table> | |||
<tr> | |||
<td>{{ form.username.label_tag }}</td> | |||
<td>{{ form.username }}</td> | |||
</tr> | |||
<tr> | |||
<td>{{ form.password.label_tag }}</td> | |||
<td>{{ form.password }}</td> | |||
</tr> | |||
</table> | |||
<input type="submit" value="Anmelden"> | |||
<input type="hidden" name="next" value="{{ next }}"> | |||
</form> | |||
<p> | |||
<a href="{% url 'password_reset' %}">Passwort vergessen?</a> | |||
</p> | |||
{% endblock %} |