Brute-Force-Rename - Don't expect this to run.

This commit is contained in:
2025-10-02 13:47:42 +02:00
parent 4259393916
commit 20359cf33d
25 changed files with 83 additions and 259 deletions

View File

@@ -43,7 +43,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'standards',
'dokumente',
'abschnitte',
'stichworte',
'referenzen',

View File

@@ -19,7 +19,7 @@ from django.urls import include, path, re_path
from django.conf import settings
from django.conf.urls.static import static
from diagramm_proxy.views import DiagrammProxyView
import standards.views
import dokumente.views
import pages.views
import referenzen.views
@@ -28,7 +28,7 @@ admin.site.site_header="Autorenumgebung"
urlpatterns = [
path('',pages.views.startseite),
path('search/',pages.views.search),
path('standards/', include("standards.urls")),
path('dokumente/', include("dokumente.urls")),
path('autorenumgebung/', admin.site.urls),
path('stichworte/', include("stichworte.urls")),
path('referenzen/', referenzen.views.tree, name="referenz_tree"),

View File

@@ -1,6 +1,7 @@
from django.apps import AppConfig
class standardsConfig(AppConfig):
class DokumenteConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'standards'
name = 'dokumente'
verbose_name="Dokumente"

View File

@@ -4,8 +4,8 @@ from pathlib import Path
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from standards.models import (
Standard,
from dokumente.models import (
Dokument,
Dokumententyp,
Thema,
Vorgabe,
@@ -64,7 +64,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.WARNING("Dry run: no database changes will be made."))
# get or create Standard (we want a real instance even in purge to count existing rows)
standard, created = Standard.objects.get_or_create(
dokument, created = Dokument.objects.get_or_create(
nummer=nummer,
defaults={
"dokumententyp": dokumententyp,
@@ -80,12 +80,12 @@ class Command(BaseCommand):
# purge (Einleitung + Geltungsbereich + Vorgaben cascade)
if purge:
qs_vorgaben = standard.vorgaben.all()
qs_vorgaben = dokument.vorgaben.all()
qs_check = Checklistenfrage.objects.filter(vorgabe__in=qs_vorgaben)
qs_kurz = VorgabeKurztext.objects.filter(abschnitt__in=qs_vorgaben)
qs_lang = VorgabeLangtext.objects.filter(abschnitt__in=qs_vorgaben)
qs_gb = Geltungsbereich.objects.filter(geltungsbereich=standard)
qs_einl = Einleitung.objects.filter(einleitung=standard)
qs_gb = Geltungsbereich.objects.filter(geltungsbereich=dokument)
qs_einl = Einleitung.objects.filter(einleitung=dokument)
c_vorgaben = qs_vorgaben.count()
c_check = qs_check.count()
@@ -265,7 +265,7 @@ class Command(BaseCommand):
))
else:
Einleitung.objects.create(
einleitung=standard,
einleitung=dokument,
abschnitttyp=sektion["typ"],
inhalt=sektion["inhalt"],
)
@@ -278,7 +278,7 @@ class Command(BaseCommand):
))
else:
Geltungsbereich.objects.create(
geltungsbereich=standard,
geltungsbereich=dokument,
abschnitttyp=sektion["typ"],
inhalt=sektion["inhalt"],
)
@@ -315,7 +315,7 @@ class Command(BaseCommand):
else:
vorgabe = Vorgabe.objects.create(
nummer=v["nummer"],
dokument=standard,
dokument=dokument,
thema=thema,
titel=v["titel"],
gueltigkeit_von=timezone.now().date(),
@@ -347,6 +347,6 @@ class Command(BaseCommand):
)
self.stdout.write(self.style.SUCCESS(
"Dry run complete" if dry_run else f"Imported standard {nummer} {name} with {len(vorgaben_data)} Vorgaben"
"Dry run complete" if dry_run else f"Imported dokument {nummer} {name} with {len(vorgaben_data)} Vorgaben"
))

View File

@@ -3,7 +3,7 @@
<html>
<head>
<meta charset="utf-8">
<title>{{ standard }}</title>
<title>{{ dokument }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
{% load static %}
</head>
@@ -11,7 +11,7 @@
<h1>{{ standard.nummer }} {{ standard.name }}</h1>
<h1>{{ dokument.nummer }} {{ dokument.name }}</h1>
<h2>Checkliste</h2>

View File

@@ -1,40 +1,40 @@
{% extends "base.html" %}
{% block title %}{{ standard }}{% endblock %}
{% block title %}{{ dokument }}{% endblock %}
{% block content %}
<h1>{{ standard.nummer }} {{ standard.name }}</h1>
{% if standard.history == True %}
<h2>Version vom {{ standard.check_date }}</h2>
<h1>{{ dokument.nummer }} {{ dokument.name }}</h1>
{% if dokument.history == True %}
<h2>Version vom {{ dokument.check_date }}</h2>
{% endif %}
<p><strong>Autoren:</strong> {{ standard.autoren.all|join:", " }}</p>
<p><strong>Prüfende:</strong> {{ standard.pruefende.all|join:", " }}</p>
<p><strong>Gültigkeit:</strong> {{ standard.gueltigkeit_von }} bis {{ standard.gueltigkeit_bis }}</p>
<p><strong>Autoren:</strong> {{ dokument.autoren.all|join:", " }}</p>
<p><strong>Prüfende:</strong> {{ dokument.pruefende.all|join:", " }}</p>
<p><strong>Gültigkeit:</strong> {{ dokument.gueltigkeit_von }} bis {{ dokument.gueltigkeit_bis }}</p>
{% if standard.einleitung_html %}
{% if dokument.einleitung_html %}
<h2>Einleitung</h2>
{% for typ, html in standard.einleitung_html %}
{% for typ, html in dokument.einleitung_html %}
<div>{{ html|safe }}</div>
{% endfor %}
{% endif %}
{% if standard.geltungsbereich_html %}
{% if dokument.geltungsbereich_html %}
<h2>Geltungsbereich</h2>
{% for typ, html in standard.geltungsbereich_html %}
{% for typ, html in dokument.geltungsbereich_html %}
<div>{{ html|safe }}</div>
{% endfor %}
{% endif %}
<h2>Vorgaben</h2>
{% for vorgabe in vorgaben %}
{% if standard.history == True or vorgabe.long_status == "active" %}
{% if dokument.history == True or vorgabe.long_status == "active" %}
<a id="{{ vorgabe.Vorgabennummer }}"></a><div class="card mb-4">
{% if vorgabe.long_status == "active"%}
<div class="card-header d-flex justify-content-between align-items-center bg-secondary text-light">
{% elif standard.history == True %}
{% elif dokument.history == True %}
<div class="card-header d-flex justify-content-between align-items-center bg-danger-subtle">
{% endif %}
<h3 class="h5 m-0">{{ vorgabe.Vorgabennummer }} {{ vorgabe.titel }}
{% if vorgabe.long_status != "active" and standard.history == True %}<span class="text-danger"> ({{ vorgabe.long_status}})</span>{% endif %}
{% if vorgabe.long_status != "active" and dokument.history == True %}<span class="text-danger"> ({{ vorgabe.long_status}})</span>{% endif %}
</h3>
{% if vorgabe.relevanzset %}
<span class="badge bg-light text-black"> Relevanz:

View File

@@ -1,12 +1,12 @@
<h1>{{ standard.nummer }} {{ standard.name }}</h1>
<h1>{{ dokument.nummer }} {{ dokument.name }}</h1>
<p><strong>Autoren:</strong> {{ standard.autoren.all|join:", " }}</p>
<p><strong>Prüfende:</strong> {{ standard.pruefende.all|join:", " }}</p>
<p><strong>Gültigkeit:</strong> {{ standard.gueltigkeit_von }} bis {{ standard.gueltigkeit_bis }}</p>
<p><strong>Autoren:</strong> {{ dokument.autoren.all|join:", " }}</p>
<p><strong>Prüfende:</strong> {{ dokument.pruefende.all|join:", " }}</p>
<p><strong>Gültigkeit:</strong> {{ dokument.gueltigkeit_von }} bis {{ dokument.gueltigkeit_bis }}</p>
{% if standard.geltungsbereich_html %}
{% if dokument.geltungsbereich_html %}
<h2>Geltungsbereich</h2>
{% for typ, html in standard.geltungsbereich_html %}
{% for typ, html in dokument.geltungsbereich_html %}
<div>{{ html|safe }}</div>
{% endfor %}
{% endif %}

View File

@@ -2,10 +2,10 @@
{% block content %}
<h1>Standards Informatiksicherheit</h1>
<ul>
{% for standard in standards %}
{% for dokument in dokumente %}
<li>
<a href="{% url 'standard_detail' nummer=standard.nummer %}">
{{ standard.nummer }} {{ standard.name }}
<a href="{% url 'dokument_detail' nummer=dokument.nummer %}">
{{ dokument.nummer }} {{ dokument.name }}
</a>
</li>
{% endfor %}

11
dokumente/urls.py Normal file
View File

@@ -0,0 +1,11 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.dokument_list, name='dokument_list'),
path('<str:nummer>/', views.dokument_detail, name='dokument_detail'),
path('<str:nummer>/history/<str:check_date>/', views.dokument_detail),
path('<str:nummer>/history/', views.dokument_detail, {"check_date":"today"}, name='dokument_history'),
path('<str:nummer>/checkliste/', views.dokument_checkliste, name='dokument_checkliste')
]

View File

@@ -8,27 +8,27 @@ import parsedatetime
calendar=parsedatetime.Calendar()
def standard_list(request):
standards = Dokument.objects.all()
return render(request, 'standards/standard_list.html',
{'standards': standards}
def dokument_list(request):
dokumente = Dokument.objects.all()
return render(request, 'dokumente/dokument_list.html',
{'dokumente': dokumente}
)
def standard_detail(request, nummer,check_date=""):
standard = get_object_or_404(Dokument, nummer=nummer)
def dokument_detail(request, nummer,check_date=""):
dokument = get_object_or_404(Dokument, nummer=nummer)
if check_date:
check_date = calendar.parseDT(check_date)[0].date()
standard.history = True
dokument.history = True
else:
check_date = date.today()
standard.history = False
standard.check_date=check_date
vorgaben = list(standard.vorgaben.order_by("thema","nummer").select_related("thema","dokument")) # convert queryset to list so we can attach attributes
dokument.history = False
dokument.check_date=check_date
vorgaben = list(dokument.vorgaben.order_by("thema","nummer").select_related("thema","dokument")) # convert queryset to list so we can attach attributes
standard.geltungsbereich_html = render_textabschnitte(standard.geltungsbereich_set.order_by("order").select_related("abschnitttyp"))
standard.einleitung_html=render_textabschnitte(standard.einleitung_set.order_by("order"))
dokument.geltungsbereich_html = render_textabschnitte(dokument.geltungsbereich_set.order_by("order").select_related("abschnitttyp"))
dokument.einleitung_html=render_textabschnitte(dokument.einleitung_set.order_by("order"))
for vorgabe in vorgaben:
# Prepare Kurztext HTML
vorgabe.kurztext_html = render_textabschnitte(vorgabe.vorgabekurztext_set.order_by("order").select_related("abschnitttyp","abschnitt"))
@@ -41,17 +41,17 @@ def standard_detail(request, nummer,check_date=""):
referenz_items.append(r.Path())
vorgabe.referenzpfade = referenz_items
return render(request, 'standards/standard_detail.html', {
'standard': standard,
return render(request, 'dokumente/dokument_detail.html', {
'dokument': dokument,
'vorgaben': vorgaben,
})
def standard_checkliste(request, nummer):
standard = get_object_or_404(Dokument, nummer=nummer)
vorgaben = list(standard.vorgaben.all())
return render(request, 'standards/standard_checkliste.html', {
'standard': standard,
def dokument_checkliste(request, nummer):
dokument = get_object_or_404(Dokument, nummer=nummer)
vorgaben = list(dokument.vorgaben.all())
return render(request, 'dokumente/dokument_checkliste.html', {
'dokument': dokument,
'vorgaben': vorgaben,
})

View File

@@ -3,9 +3,9 @@
{% block content %}
<h1 class="mb-4">Suchresultate für {{ suchbegriff }}</h1>
{% if resultat.geltungsbereich %}
<h2>Standards mit "{{suchbegriff}}" im Geltungsbereich</h2>
{% for standard,geltungsbereich in resultat.geltungsbereich.items %}
<h4>{{ standard }}</h4>
<h2>Dokumente mit "{{suchbegriff}}" im Geltungsbereich</h2>
{% for dokument,geltungsbereich in resultat.geltungsbereich.items %}
<h4>{{ dokument }}</h4>
{% for typ, html in geltungsbereich %}
<div>{{ html|highlighttext:suchbegriff|safe }}</div>
{% endfor %}
@@ -14,11 +14,11 @@
{% if resultat.kurztext %}
<h2>Vorgaben mit "{{ suchbegriff }}" im Kurztext</h2>
{% for standard, vorgaben in resultat.kurztext.items %}
<h4>{{ standard }}</h4>
{% for dokument, vorgaben in resultat.kurztext.items %}
<h4>{{ dokument }}</h4>
<ul>
{% for vorgabe in vorgaben %}
<li><a href="{% url 'standard_detail' nummer=vorgabe.dokument.nummer %}#{{vorgabe.Vorgabennummer}}">{{vorgabe}}</a></li>
<li><a href="{% url 'dokument_detail' nummer=vorgabe.dokument.nummer %}#{{vorgabe.Vorgabennummer}}">{{vorgabe}}</a></li>
{% endfor %}
</ul>
{% endfor %}
@@ -26,11 +26,11 @@
{% if resultat.langtext %}
<h2>Vorgaben mit "{{ suchbegriff }}" im Langtext</h2>
{% for standard, vorgaben in resultat.langtext.items %}
<h4>{{ standard }}</h4>
{% for dokument, vorgaben in resultat.langtext.items %}
<h4>{{ dokument }}</h4>
<ul>
{% for vorgabe in vorgaben %}
<li><a href="{% url 'standard_detail' nummer=vorgabe.dokument.nummer %}#{{vorgabe.Vorgabennummer}}">{{vorgabe}}</a></li>
<li><a href="{% url 'dokument_detail' nummer=vorgabe.dokument.nummer %}#{{vorgabe.Vorgabennummer}}">{{vorgabe}}</a></li>
{% endfor %}
</ul>
{% endfor %}

View File

@@ -1,12 +1,12 @@
from django.shortcuts import render
from abschnitte.utils import render_textabschnitte
from standards.models import Dokument, VorgabeLangtext, VorgabeKurztext, Geltungsbereich
from dokumente.models import Dokument, VorgabeLangtext, VorgabeKurztext, Geltungsbereich
from itertools import groupby
import datetime
def startseite(request):
standards=list(Dokument.objects.all())
return render(request, 'startseite.html', {"standards":standards,})
dokumente=list(Dokument.objects.all())
return render(request, 'startseite.html', {"dokumente":dokumente,})
def search(request):
if request.method == "GET":

View File

@@ -1,177 +0,0 @@
# Standards/management/commands/import_standard.py
import re
from pathlib import Path
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from standards.models import (
Standard,
Vorgabe,
VorgabeKurztext,
VorgabeLangtext,
Geltungsbereich,
Dokumententyp,
Thema,
)
from abschnitte.models import AbschnittTyp
class Command(BaseCommand):
help = "Import a security standard from a structured text file"
def add_arguments(self, parser):
parser.add_argument("file_path", type=str, help="Path to the plaintext file")
parser.add_argument("--nummer", required=True, help="Standard number (e.g., STD-001)")
parser.add_argument("--name", required=True, help="Standard name (e.g., IT-Sicherheit Container)")
parser.add_argument("--dokumententyp", required=True, help="Dokumententyp name")
parser.add_argument("--gueltigkeit_von", default=None, help="Start date (YYYY-MM-DD)")
parser.add_argument("--gueltigkeit_bis", default=None, help="End date (YYYY-MM-DD)")
parser.add_argument("--dry-run", action="store_true", help="Perform a dry run without saving to the database")
parser.add_argument("--verbose", action="store_true", help="Verbose output for dry run")
def handle(self, *args, **options):
dry_run = options["dry_run"]
verbose = options["verbose"]
file_path = Path(options["file_path"])
if not file_path.exists():
raise CommandError(f"File {file_path} does not exist")
nummer = options["nummer"]
name = options["name"]
dokumententyp_name = options["dokumententyp"]
try:
dokumententyp = Dokumententyp.objects.get(name=dokumententyp_name)
except Dokumententyp.DoesNotExist:
raise CommandError(f"Dokumententyp '{dokumententyp_name}' does not exist")
if dry_run:
self.stdout.write(self.style.WARNING("Dry run: no database changes will be made"))
# Create or get the Standard
if dry_run:
standard = {"nummer": nummer, "name": name, "dokumententyp": dokumententyp}
else:
standard, created = Standard.objects.get_or_create(
nummer=nummer,
defaults={
"dokumententyp": dokumententyp,
"name": name,
"gueltigkeit_von": options["gueltigkeit_von"],
"gueltigkeit_bis": options["gueltigkeit_bis"],
},
)
if not created:
self.stdout.write(self.style.WARNING(f"Standard {nummer} already exists, updating content"))
# Read and parse the file
content = file_path.read_text(encoding="utf-8")
blocks = re.split(r"^>>>", content, flags=re.MULTILINE)
blocks = [b.strip() for b in blocks if b.strip()]
geltungsbereich_sections = []
current_vorgabe = None
vorgaben_data = []
current_context = "geltungsbereich"
abschnittstyp_headers = ["text", "liste geordnet", "liste ungeordnet"]
for block in blocks:
lines = block.splitlines()
header = lines[0].strip()
text = "\n".join(lines[1:]).strip()
header_lower = header.lower()
# Determine AbschnittTyp if applicable
abschnitt_typ = None
if header_lower in abschnittstyp_headers:
try:
abschnitt_typ = AbschnittTyp.objects.get(abschnitttyp=header_lower)
except AbschnittTyp.DoesNotExist:
self.stdout.write(self.style.WARNING(f"AbschnittTyp '{header_lower}' not found, defaulting to 'text'"))
abschnitt_typ = AbschnittTyp.objects.get(abschnitttyp="text")
if header_lower == "geltungsbereich":
current_context = "geltungsbereich"
elif header_lower.startswith("vorgabe"):
if current_vorgabe:
vorgaben_data.append(current_vorgabe)
thema_name = header.split(" ", 1)[1].strip()
current_vorgabe = {"thema": thema_name, "titel": "", "nummer": None, "kurztext": [], "langtext": []}
current_context = "vorgabe_none"
elif header_lower.startswith("titel") and current_vorgabe:
current_vorgabe["titel"] = text
elif header_lower.startswith("nummer") and current_vorgabe:
nummer_match = re.search(r"\d+", header)
if nummer_match:
current_vorgabe["nummer"] = int(nummer_match.group())
current_context = "vorgabe_none"
elif header_lower == "kurztext":
current_context = "vorgabe_kurztext"
elif header_lower == "langtext":
current_context = "vorgabe_langtext"
elif header_lower in abschnittstyp_headers:
abschnitt = {"inhalt": text, "typ": abschnitt_typ}
if current_context == "geltungsbereich":
geltungsbereich_sections.append(abschnitt)
if dry_run and verbose:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Geltungsbereich Abschnitt (Abschnittstyp: {abschnitt_typ}): {text[:50]}..."))
elif current_context == "vorgabe_kurztext" and current_vorgabe:
current_vorgabe["kurztext"].append(abschnitt)
if dry_run and verbose:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Vorgabe {current_vorgabe['nummer']} Kurztext Abschnitt (Abschnittstyp: {abschnitt_typ}): {text[:50]}..."))
elif current_context == "vorgabe_langtext" and current_vorgabe:
current_vorgabe["langtext"].append(abschnitt)
if dry_run and verbose:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Vorgabe {current_vorgabe['nummer']} Langtext Abschnitt (Abschnittstyp: {abschnitt_typ}): {text[:50]}..."))
if current_vorgabe:
vorgaben_data.append(current_vorgabe)
# Save Geltungsbereich
for sektion in geltungsbereich_sections:
if dry_run:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Would create Geltungsbereich Abschnitt (Abschnittstyp: {sektion['typ']}): {sektion['inhalt'][:50]}..."))
else:
Geltungsbereich.objects.create(
geltungsbereich=standard,
abschnitttyp=sektion["typ"],
inhalt=sektion["inhalt"],
)
# Save Vorgaben
for v in vorgaben_data:
try:
thema = Thema.objects.get(name=v["thema"])
except Thema.DoesNotExist:
self.stdout.write(self.style.WARNING(f"Thema '{v['thema']}' not found, skipping Vorgabe {v['nummer']}"))
continue
if dry_run:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Would create Vorgabe {v['nummer']}: '{v['titel']}' (Thema: {v['thema']})"))
for sektion in v["kurztext"]:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Kurztext Abschnitt (Abschnittstyp: {sektion['typ']}): {sektion['inhalt'][:50]}..."))
for sektion in v["langtext"]:
self.stdout.write(self.style.SUCCESS(f"[DRY RUN] Langtext Abschnitt (Abschnittstyp: {sektion['typ']}): {sektion['inhalt'][:50]}..."))
else:
vorgabe = Vorgabe.objects.create(
nummer=v["nummer"],
dokument=standard,
thema=thema,
titel=v["titel"],
gueltigkeit_von=timezone.now().date(),
)
for sektion in v["kurztext"]:
VorgabeKurztext.objects.create(abschnitt=vorgabe, abschnitttyp=sektion["typ"], inhalt=sektion["inhalt"])
for sektion in v["langtext"]:
VorgabeLangtext.objects.create(abschnitt=vorgabe, abschnitttyp=sektion["typ"], inhalt=sektion["inhalt"])
self.stdout.write(self.style.SUCCESS(
f"{'Dry run complete' if dry_run else f'Imported standard {standard} with {len(vorgaben_data)} Vorgaben'}"
))

View File

@@ -1,11 +0,0 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.standard_list, name='standard_list'),
path('<str:nummer>/', views.standard_detail, name='standard_detail'),
path('<str:nummer>/history/<str:check_date>/', views.standard_detail),
path('<str:nummer>/history/', views.standard_detail, {"check_date":"today"}, name='standard_history'),
path('<str:nummer>/checkliste/', views.standard_checkliste, name='standard_checkliste')
]