fix: code reformatted

This commit is contained in:
2025-05-05 18:59:00 +02:00
parent afa44011d0
commit 07ea49a035
13 changed files with 139 additions and 93 deletions

View File

@@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'korrekturmanagementsystem.settings') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "korrekturmanagementsystem.settings")
application = get_asgi_application() application = get_asgi_application()

View File

@@ -20,7 +20,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-^20f=_*q+z6a3x_-7)10ku8e)1-k3!-4it1^@+7s0u3zpjcgn2' SECRET_KEY = "django-insecure-^20f=_*q+z6a3x_-7)10ku8e)1-k3!-4it1^@+7s0u3zpjcgn2"
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
@@ -31,52 +31,52 @@ ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'ticketsystem.apps.TicketsystemConfig', "ticketsystem.apps.TicketsystemConfig",
'django.contrib.admin', "django.contrib.admin",
'django.contrib.auth', "django.contrib.auth",
'django.contrib.contenttypes', "django.contrib.contenttypes",
'django.contrib.sessions', "django.contrib.sessions",
'django.contrib.messages', "django.contrib.messages",
'django.contrib.staticfiles', "django.contrib.staticfiles",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', "django.middleware.security.SecurityMiddleware",
'django.contrib.sessions.middleware.SessionMiddleware', "django.contrib.sessions.middleware.SessionMiddleware",
'django.middleware.common.CommonMiddleware', "django.middleware.common.CommonMiddleware",
'django.middleware.csrf.CsrfViewMiddleware', "django.middleware.csrf.CsrfViewMiddleware",
'django.contrib.auth.middleware.AuthenticationMiddleware', "django.contrib.auth.middleware.AuthenticationMiddleware",
'django.contrib.messages.middleware.MessageMiddleware', "django.contrib.messages.middleware.MessageMiddleware",
'django.middleware.clickjacking.XFrameOptionsMiddleware', "django.middleware.clickjacking.XFrameOptionsMiddleware",
] ]
ROOT_URLCONF = 'korrekturmanagementsystem.urls' ROOT_URLCONF = "korrekturmanagementsystem.urls"
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', "BACKEND": "django.template.backends.django.DjangoTemplates",
'DIRS': [], "DIRS": [],
'APP_DIRS': True, "APP_DIRS": True,
'OPTIONS': { "OPTIONS": {
'context_processors': [ "context_processors": [
'django.template.context_processors.request', "django.template.context_processors.request",
'django.contrib.auth.context_processors.auth', "django.contrib.auth.context_processors.auth",
'django.contrib.messages.context_processors.messages', "django.contrib.messages.context_processors.messages",
], ],
}, },
}, },
] ]
WSGI_APPLICATION = 'korrekturmanagementsystem.wsgi.application' WSGI_APPLICATION = "korrekturmanagementsystem.wsgi.application"
# Database # Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases # https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { "default": {
'ENGINE': 'django.db.backends.sqlite3', "ENGINE": "django.db.backends.sqlite3",
'NAME': BASE_DIR / 'db.sqlite3', "NAME": BASE_DIR / "db.sqlite3",
} }
} }
@@ -86,16 +86,18 @@ DATABASES = {
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', "NAME": (
"django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
),
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
}, },
] ]
@@ -103,9 +105,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/ # https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = 'de-de' LANGUAGE_CODE = "de-de"
TIME_ZONE = 'CET' TIME_ZONE = "CET"
USE_I18N = True USE_I18N = True
@@ -115,9 +117,9 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/ # https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = 'static/' STATIC_URL = "static/"
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

View File

@@ -14,10 +14,11 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
urlpatterns = [ urlpatterns = [
path("ticketsystem/", include("ticketsystem.urls")), path("ticketsystem/", include("ticketsystem.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
] ]

View File

@@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'korrekturmanagementsystem.settings') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "korrekturmanagementsystem.settings")
application = get_wsgi_application() application = get_wsgi_application()

View File

@@ -6,7 +6,9 @@ import sys
def main(): def main():
"""Run administrative tasks.""" """Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'korrekturmanagementsystem.settings') os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "korrekturmanagementsystem.settings"
)
try: try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError as exc: except ImportError as exc:
@@ -18,5 +20,5 @@ def main():
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@@ -2,4 +2,4 @@ from django.contrib import admin
from .models import Ticket from .models import Ticket
admin.site.register(Ticket) admin.site.register(Ticket)

View File

@@ -2,5 +2,5 @@ from django.apps import AppConfig
class TicketsystemConfig(AppConfig): class TicketsystemConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = "django.db.models.BigAutoField"
name = 'ticketsystem' name = "ticketsystem"

View File

@@ -7,5 +7,7 @@ class CommentForm(forms.ModelForm):
model = Comment model = Comment
fields = ["text"] fields = ["text"]
widgets = { widgets = {
"text": forms.Textarea(attrs={"rows": 3, "placeholder": "Kommentar schreiben..."}), "text": forms.Textarea(
attrs={"rows": 3, "placeholder": "Kommentar schreiben..."}
),
} }

View File

@@ -4,23 +4,33 @@ from django.contrib.auth.models import User
class Ticket(models.Model): class Ticket(models.Model):
STATUS_CHOICES = [ STATUS_CHOICES = [
('open', 'Offen'), ("open", "Offen"),
('in_progress', 'In Bearbeitung'), ("in_progress", "In Bearbeitung"),
('closed', 'Geschlossen'), ("closed", "Geschlossen"),
] ]
PRIORITY_CHOICES = [ PRIORITY_CHOICES = [
('low', 'Niedrig'), ("low", "Niedrig"),
('medium', 'Mittel'), ("medium", "Mittel"),
('high', 'Hoch'), ("high", "Hoch"),
] ]
title = models.CharField(max_length=200) title = models.CharField(max_length=200)
description = models.TextField() description = models.TextField()
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open') status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="open")
priority = models.CharField(max_length=10, choices=PRIORITY_CHOICES, default='medium') priority = models.CharField(
created_by = models.ForeignKey(User, related_name='tickets_created', on_delete=models.CASCADE) max_length=10, choices=PRIORITY_CHOICES, default="medium"
assigned_to = models.ForeignKey(User, related_name='tickets_assigned', null=True, blank=True, on_delete=models.SET_NULL) )
created_by = models.ForeignKey(
User, related_name="tickets_created", on_delete=models.CASCADE
)
assigned_to = models.ForeignKey(
User,
related_name="tickets_assigned",
null=True,
blank=True,
on_delete=models.SET_NULL,
)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@@ -29,7 +39,9 @@ class Ticket(models.Model):
class Comment(models.Model): class Comment(models.Model):
ticket = models.ForeignKey("Ticket", on_delete=models.CASCADE, related_name="comments") ticket = models.ForeignKey(
"Ticket", on_delete=models.CASCADE, related_name="comments"
)
author = models.ForeignKey(User, on_delete=models.CASCADE) author = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField() text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
@@ -39,7 +51,9 @@ class Comment(models.Model):
class TicketHistory(models.Model): class TicketHistory(models.Model):
ticket = models.ForeignKey("Ticket", on_delete=models.CASCADE, related_name="history") ticket = models.ForeignKey(
"Ticket", on_delete=models.CASCADE, related_name="history"
)
changed_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) changed_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
changed_at = models.DateTimeField(auto_now_add=True) changed_at = models.DateTimeField(auto_now_add=True)

View File

@@ -1,16 +1,16 @@
{% block content %} {% block content %}
{% if messages %} {% if messages %}
<div style="max-width: 600px; margin: 1rem auto;"> <div style="max-width: 600px; margin: 1rem auto;">
{% for message in messages %} {% for message in messages %}
<div style="padding: 1rem; border-radius: 5px; margin-bottom: 1rem; <div style="padding: 1rem; border-radius: 5px; margin-bottom: 1rem;
background-color: {% if message.tags == 'error' %}#f8d7da background-color: {% if message.tags == 'error' %}#f8d7da
{% elif message.tags == 'success' %}#d4edda {% elif message.tags == 'success' %}#d4edda
{% else %}#fff3cd{% endif %}; {% else %}#fff3cd{% endif %};
color: #333;"> color: #333;">
{{ message }} {{ message }}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<style> <style>
.ticket-container { .ticket-container {
@@ -133,21 +133,21 @@
</form> </form>
{% endif %} {% endif %}
<div style="margin-top: 3rem;"> <div style="margin-top: 3rem;">
<h2>🕓 Bearbeitungshistorie</h2> <h2>🕓 Bearbeitungshistorie</h2>
{% if ticket.history.exists %} {% if ticket.history.exists %}
<ul style="list-style: none; padding: 0;"> <ul style="list-style: none; padding: 0;">
{% for entry in ticket.history.all %} {% for entry in ticket.history.all %}
<li style="margin-bottom: 1rem; background-color: #f9f9f9; border-left: 4px solid #ccc; padding: 0.5rem 1rem;"> <li style="margin-bottom: 1rem; background-color: #f9f9f9; border-left: 4px solid #ccc; padding: 0.5rem 1rem;">
<strong>{{ entry.changed_by.username }}</strong> <strong>{{ entry.changed_by.username }}</strong>
hat <code>{{ entry.field }}</code> geändert:<br> hat <code>{{ entry.field }}</code> geändert:<br>
<em>{{ entry.old_value }}</em><strong>{{ entry.new_value }}</strong><br> <em>{{ entry.old_value }}</em><strong>{{ entry.new_value }}</strong><br>
<small>am {{ entry.changed_at|date:"d.m.Y H:i" }}</small> <small>am {{ entry.changed_at|date:"d.m.Y H:i" }}</small>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% else %} {% else %}
<p><em>Keine Änderungen bisher.</em></p> <p><em>Keine Änderungen bisher.</em></p>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -1,5 +1,5 @@
{% block content %} {% block content %}
<style> <style>
.form-container { .form-container {
max-width: 600px; max-width: 600px;
margin: 2rem auto; margin: 2rem auto;
@@ -44,14 +44,26 @@
.form-container button:hover { .form-container button:hover {
background-color: #0056b3; background-color: #0056b3;
} }
</style> </style>
<div class="form-container"> <div class="form-container">
<h1>🎫 Neues Ticket erstellen</h1> <h1>
{% if object.pk %}
✏️ Ticket bearbeiten
{% else %}
🎫 Neues Ticket erstellen
{% endif %}
</h1>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<button type="submit">Erstellen</button> <button type="submit">
{% if object.pk %}
Speichern
{% else %}
Erstellen
{% endif %}
</button>
</form> </form>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -1,7 +1,13 @@
from django.urls import path from django.urls import path
from . import views from . import views
from .views import TicketListView, TicketCreateView, TicketUpdateView, HomeView, TicketDetailView from .views import (
TicketListView,
TicketCreateView,
TicketUpdateView,
HomeView,
TicketDetailView,
)
urlpatterns = [ urlpatterns = [
# /ticketsystem/ # /ticketsystem/
@@ -13,4 +19,4 @@ urlpatterns = [
# /ticketsystem/new/ # /ticketsystem/new/
path("new/", TicketCreateView.as_view(), name="create"), path("new/", TicketCreateView.as_view(), name="create"),
path("<int:pk>/modify/", TicketUpdateView.as_view(), name="modify"), path("<int:pk>/modify/", TicketUpdateView.as_view(), name="modify"),
] ]

View File

@@ -5,7 +5,6 @@ from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from .forms import CommentForm from .forms import CommentForm
from django.urls import reverse from django.urls import reverse
from django.http import HttpResponseForbidden
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages from django.contrib import messages
from django.shortcuts import redirect from django.shortcuts import redirect
@@ -66,12 +65,19 @@ class TicketDetailView(FormMixin, DetailView):
class TicketCreateView(CreateView): class TicketCreateView(CreateView):
model = Ticket model = Ticket
fields = ["title", "description", "priority", "assigned_to"] # user & status wird automatisch gesetzt fields = [
"title",
"description",
"priority",
"assigned_to",
] # user & status wird automatisch gesetzt
template_name = "ticketsystem/ticket_form.html" template_name = "ticketsystem/ticket_form.html"
success_url = reverse_lazy("ticket-list") success_url = reverse_lazy("ticket-list")
def form_valid(self, form): def form_valid(self, form):
form.instance.created_by = self.request.user # Der angemeldete User wird automatisch gesetzt form.instance.created_by = (
self.request.user
) # Der angemeldete User wird automatisch gesetzt
form.instance.status = "open" # Neues Ticket beginnt immer als "offen" form.instance.status = "open" # Neues Ticket beginnt immer als "offen"
return super().form_valid(form) return super().form_valid(form)
@@ -80,7 +86,6 @@ class TicketUpdateView(LoginRequiredMixin, UpdateView):
model = Ticket model = Ticket
fields = ["title", "description", "status", "priority", "assigned_to"] fields = ["title", "description", "status", "priority", "assigned_to"]
template_name = "ticketsystem/ticket_form.html" template_name = "ticketsystem/ticket_form.html"
success_url = reverse_lazy("ticket-list")
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
ticket = self.get_object() ticket = self.get_object()
@@ -99,7 +104,7 @@ class TicketUpdateView(LoginRequiredMixin, UpdateView):
response = super().form_valid(form) # Speichert das Ticket response = super().form_valid(form) # Speichert das Ticket
tracked_fields = ["status", "description"] tracked_fields = ["status", "description", "priority"]
for field in tracked_fields: for field in tracked_fields:
if field in form.changed_data: if field in form.changed_data:
old_value = getattr(original, field) old_value = getattr(original, field)
@@ -111,5 +116,7 @@ class TicketUpdateView(LoginRequiredMixin, UpdateView):
old_value=str(old_value), old_value=str(old_value),
new_value=str(new_value), new_value=str(new_value),
) )
return response return response
def get_success_url(self):
return reverse_lazy("detail", kwargs={"pk": self.object.pk})