/venv/ | |||||
/db.sqlite3 | |||||
/playground.py | |||||
/playground2.py |
#!/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() |
""" | |||||
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() |
""" | |||||
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/' | |||||
""" | |||||
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')), | |||||
] | |||||
""" | |||||
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() |
from django.contrib import admin | |||||
from .models import Notice | |||||
admin.site.register(Notice) | |||||
from django.apps import AppConfig | |||||
class PollsConfig(AppConfig): | |||||
default_auto_field = 'django.db.models.BigAutoField' | |||||
name = 'polls' |
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) |
# 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()), | |||||
], | |||||
), | |||||
] | |||||
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() | |||||
from django.test import TestCase | |||||
# Create your tests here. |
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'), | |||||
] | |||||
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) | |||||
Django>=4.2.6 |
<!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> | |||||
{% 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 %} | |||||
{% 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 %} | |||||
{% 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 %} |