Add navigation registry and template integration for modular apps
- Introduced risks/navigation_registry.py for central navigation registry - Added risks/templatetags/navigation.py to render registry entries - Created template fragment risks/templates/risks/_extra_nav.html - Updated README.md with integration instructions - Prepared risks/base.html to include extra navigation automatically
This commit is contained in:
parent
7401ce154c
commit
ac3c6db486
6 changed files with 206 additions and 0 deletions
154
README.md
Normal file
154
README.md
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
# Modul-Integration in das *risks* Projekt
|
||||||
|
|
||||||
|
Dieses Dokument beschreibt, wie weitere Apps (z. B. **ToDo**) in dein ISO-27001 Risk-Management Projekt (App heißt `risks`) integriert werden.
|
||||||
|
Alle Apps im Bestand sind/werden nach demselben Muster aufgebaut und registrieren sich selbst in der Navigation, wenn sie installiert sind und vorhandene Permissions passen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schritte zur Einbindung einer neuen App
|
||||||
|
|
||||||
|
### 1. Submodul hinzufügen
|
||||||
|
|
||||||
|
Füge das gewünschte App-Repo als Git-Submodul hinzu:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule add <git-url-der-app> <ziel-verzeichnis>
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispiel für ToDo-App:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule add https://skulldev.de/Skull-IT/todo-app.git todo
|
||||||
|
```
|
||||||
|
|
||||||
|
> Wichtig: Der Zielpfad sollte dem App-Namen entsprechen (`todo` etc).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. App in `INSTALLED_APPS` aktivieren
|
||||||
|
|
||||||
|
In deinem Projekt unter `config/settings.py` oder dem entsprechenden Settings-Modul:
|
||||||
|
|
||||||
|
```python
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
# bestehende Apps
|
||||||
|
"risks",
|
||||||
|
"todo", # neu hinzugefügte App
|
||||||
|
# … weitere
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Damit registriert Django Models, Migrations, Templates & static files der App.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. URLs einbinden
|
||||||
|
|
||||||
|
In deiner zentralen `urls.py` (unter `config/` oder wo dein Root URLs definiert sind) muss die neue App eingebunden werden:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from django.urls import include, path
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# …
|
||||||
|
path("todo/", include("todo.urls", namespace="todo")),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Damit werden die Views der App über `/todo/` erreichbar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Navigation (automatisch)
|
||||||
|
|
||||||
|
#### Registry-Ansatz
|
||||||
|
|
||||||
|
* In `risks` existiert eine Navigation-Registry.
|
||||||
|
* Jede App registriert sich selbst in dieser Registry mit Label, URL-Name, und erforderlicher Permission.
|
||||||
|
* `risks` rendert automatisch alle registrierten Navigationseinträge im Menü, sofern installiert + Benutzer berechtigt.
|
||||||
|
|
||||||
|
#### Beispiel: Registrierung in der neuen App (`apps.py`)
|
||||||
|
|
||||||
|
```python
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
class TodoConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "todo"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
try:
|
||||||
|
from risks.navigation_registry import register
|
||||||
|
register(
|
||||||
|
label="ToDo",
|
||||||
|
url_name="todo:list", # Name, wie in todo.urls
|
||||||
|
permission="todo.view_task", # Permission nötig
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# risks App ist nicht installiert → nichts machen
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Verhalten
|
||||||
|
|
||||||
|
* Ist die App **nicht installiert** → kein Menüpunkt
|
||||||
|
* Ist sie **installiert, aber User hat keine entsprechende Permission** → kein Menüpunkt
|
||||||
|
* Ist sie **installiert und hat User die Permission** → Menüpunkt erscheint automatisch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Base-Template-Vererbung
|
||||||
|
|
||||||
|
* Läuft die neue App **allein** (Standalone/Demo) → sie liefert ein eigenes `base.html`.
|
||||||
|
* Wenn sie im `risks` Projekt eingebunden ist → sie erbt das `base.html` aus `risks`.
|
||||||
|
|
||||||
|
Dies funktioniert über die Reihenfolge in `INSTALLED_APPS` oder über ein optionales Setting wie z. B. `TODO_BASE_TEMPLATE`, welches gesetzt werden kann, wenn `risks` das Base vorgibt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. Migration & Datenbankstruktur
|
||||||
|
|
||||||
|
Nach Einbindung:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
Stelle sicher, dass Migrationen der neuen App mitlaufen und keine Konflikte bestehen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. Permissions setzen
|
||||||
|
|
||||||
|
Die neue App definiert eigene Permissions via `Meta` in `models` oder explizit via Migration.
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
* `todo.view_task` → um den Menüpunkt und Zugriffe zu erlauben
|
||||||
|
* Weitere wie `todo.add_task`, `todo.change_task`, `todo.delete_task`
|
||||||
|
|
||||||
|
Rechte können über Django Admin oder Migration vergeben werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. Tests ausführen
|
||||||
|
|
||||||
|
Sicherheitshalber:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python manage.py test todo
|
||||||
|
```
|
||||||
|
|
||||||
|
So siehst du, ob die App sauber arbeitet und integriert ist.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. Checkliste
|
||||||
|
|
||||||
|
* [ ] Submodul hinzugefügt
|
||||||
|
* [ ] App in `INSTALLED_APPS` eingetragen
|
||||||
|
* [ ] URL-Einbindung in Root URLs umgesetzt
|
||||||
|
* [ ] Neue App registriert sich in der Navigation via Registry
|
||||||
|
* [ ] Migrationen ausgeführt
|
||||||
|
* [ ] Permissions gesetzt
|
||||||
|
* [ ] Navigation erscheint/dem User sichtbar, wo nötig
|
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
8
risks/navigation_registry.py
Normal file
8
risks/navigation_registry.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
registry = []
|
||||||
|
|
||||||
|
def register(label, url_name, permission=None):
|
||||||
|
registry.append({
|
||||||
|
"label": label,
|
||||||
|
"url_name": url_name,
|
||||||
|
"permission": permission,
|
||||||
|
})
|
34
risks/templatetags/navigation.py
Normal file
34
risks/templatetags/navigation.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
from django import template
|
||||||
|
from django.urls import reverse, NoReverseMatch
|
||||||
|
from django.apps import apps
|
||||||
|
from risks.navigation_registry import registry
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.inclusion_tag("risks/_extra_nav.html", takes_context=True)
|
||||||
|
def render_extra_nav(context):
|
||||||
|
user = context["request"].user
|
||||||
|
extra_items = []
|
||||||
|
|
||||||
|
for item in registry:
|
||||||
|
# Check: ist die App überhaupt installiert?
|
||||||
|
app_label = item["permission"].split(".")[0] if item["permission"] else None
|
||||||
|
if app_label and not apps.is_installed(app_label):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check: hat der User die Berechtigung?
|
||||||
|
if item["permission"] and not user.has_perm(item["permission"]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# URL auflösen
|
||||||
|
try:
|
||||||
|
url = reverse(item["url_name"])
|
||||||
|
except NoReverseMatch:
|
||||||
|
continue
|
||||||
|
|
||||||
|
extra_items.append({
|
||||||
|
"label": item["label"],
|
||||||
|
"url": url,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {"extra_items": extra_items}
|
|
@ -56,6 +56,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% load navigation %}
|
||||||
|
{% render_extra_nav %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
8
templates/risks/_extra_nav.html
Normal file
8
templates/risks/_extra_nav.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% for item in extra_items %}
|
||||||
|
<div class="navbar-item has-dropdown is-hoverable">
|
||||||
|
<a class="navbar-link">{{ item.label }}</a>
|
||||||
|
<div class="navbar-dropdown">
|
||||||
|
<a class="navbar-item" href="{{ item.url }}">{{ item.label }} Übersicht</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
Loading…
Add table
Reference in a new issue