Compare commits
24 Commits
rename_sta
...
0d0199ca62
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d0199ca62 | |||
| 5f58d660c0 | |||
| e84f25ca1d | |||
| dfb8eeef97 | |||
| 0225fb3396 | |||
| 7377ddaea3 | |||
| 67c393ecf1 | |||
| dbb3ecd5bf | |||
| 966cd46228 | |||
| 1ee9b3c46f | |||
| 8f57f5fc5b | |||
| cd7195b3aa | |||
| 020dff0871 | |||
| 1dbdbc7f3c | |||
| 4d1232b764 | |||
|
fe2e02934a
|
|||
|
add1a88ce4
|
|||
| 3c23918e1f | |||
| fa0a2a9df9 | |||
|
|
9feaf6686f | ||
| 7087be672a | |||
|
|
969141601d | ||
| d46d937e93 | |||
| 4d713b3763 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,3 +10,6 @@ keys/
|
|||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
*.kate-swp
|
*.kate-swp
|
||||||
|
|
||||||
|
# Diagram cache directory
|
||||||
|
media/diagram_cache/
|
||||||
|
|||||||
105
Documentation/DIAGRAM_CACHING.md
Normal file
105
Documentation/DIAGRAM_CACHING.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# Diagram POST Caching Implementation
|
||||||
|
|
||||||
|
This feature replaces the URL-encoded GET approach for diagram generation with POST requests and local filesystem caching.
|
||||||
|
|
||||||
|
## Changes Overview
|
||||||
|
|
||||||
|
### New Files
|
||||||
|
- `diagramm_proxy/__init__.py` - Module initialization
|
||||||
|
- `diagramm_proxy/diagram_cache.py` - Caching logic and POST request handling
|
||||||
|
- `abschnitte/management/commands/clear_diagram_cache.py` - Management command for cache clearing
|
||||||
|
|
||||||
|
### Modified Files
|
||||||
|
- `abschnitte/utils.py` - Updated `render_textabschnitte()` to use caching
|
||||||
|
- `.gitignore` - Added cache directory exclusion
|
||||||
|
|
||||||
|
## Configuration Required
|
||||||
|
|
||||||
|
Add to your Django settings file (e.g., `VorgabenUI/settings.py`):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Diagram cache settings
|
||||||
|
DIAGRAM_CACHE_DIR = 'diagram_cache' # relative to MEDIA_ROOT
|
||||||
|
|
||||||
|
# Ensure MEDIA_ROOT and MEDIA_URL are configured
|
||||||
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
```
|
||||||
|
|
||||||
|
### URL Configuration
|
||||||
|
|
||||||
|
Ensure media files are served in development. In your main `urls.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls.static import static
|
||||||
|
|
||||||
|
# ... existing urlpatterns ...
|
||||||
|
|
||||||
|
# Serve media files in development
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. When a diagram is rendered, the system computes a SHA256 hash of the diagram content
|
||||||
|
2. It checks if a cached SVG exists for that hash
|
||||||
|
3. If cached: serves the existing file
|
||||||
|
4. If not cached: POSTs content to Kroki server, saves the response, and serves it
|
||||||
|
5. Diagrams are served from `MEDIA_URL/diagram_cache/{type}/{hash}.svg`
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
- **No URL length limitations** - Content is POSTed instead of URL-encoded
|
||||||
|
- **Improved performance** - Cached diagrams are served directly from filesystem
|
||||||
|
- **Reduced server load** - Kroki server is only called once per unique diagram
|
||||||
|
- **Persistent cache** - Survives application restarts
|
||||||
|
- **Better error handling** - Graceful fallback on generation failures
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Viewing Diagrams
|
||||||
|
No changes required - diagrams will be automatically cached on first render.
|
||||||
|
|
||||||
|
### Clearing Cache
|
||||||
|
|
||||||
|
Clear all cached diagrams:
|
||||||
|
```bash
|
||||||
|
python manage.py clear_diagram_cache
|
||||||
|
```
|
||||||
|
|
||||||
|
Clear diagrams of a specific type:
|
||||||
|
```bash
|
||||||
|
python manage.py clear_diagram_cache --type plantuml
|
||||||
|
python manage.py clear_diagram_cache --type mermaid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
1. Create or view a page with diagrams
|
||||||
|
2. Verify diagrams render correctly
|
||||||
|
3. Check that `media/diagram_cache/` directory is created with cached SVGs
|
||||||
|
4. Refresh the page - second load should be faster (cache hit)
|
||||||
|
5. Check logs for cache hit/miss messages
|
||||||
|
6. Test cache clearing command
|
||||||
|
|
||||||
|
## Migration Notes
|
||||||
|
|
||||||
|
- Existing diagrams will be regenerated on first view after deployment
|
||||||
|
- The old URL-based approach is completely replaced
|
||||||
|
- No database migrations needed
|
||||||
|
- Ensure `requests` library is installed (already in requirements.txt)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Diagrams not rendering
|
||||||
|
- Check that MEDIA_ROOT and MEDIA_URL are configured correctly
|
||||||
|
- Verify Kroki server is accessible at `http://svckroki:8000`
|
||||||
|
- Check application logs for error messages
|
||||||
|
- Ensure media directory is writable
|
||||||
|
|
||||||
|
### Cache not working
|
||||||
|
- Verify Django storage configuration
|
||||||
|
- Check file permissions on media/diagram_cache directory
|
||||||
|
- Review logs for cache-related errors
|
||||||
@@ -2,3 +2,5 @@
|
|||||||
|
|
||||||
There are examples for importing text in the "Documentation"-directory. Actual documentation follows.
|
There are examples for importing text in the "Documentation"-directory. Actual documentation follows.
|
||||||
|
|
||||||
|
Documentation on Confluence so far.
|
||||||
|
This commit should be signed.
|
||||||
|
|||||||
1
abschnitte/management/__init__.py
Normal file
1
abschnitte/management/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Management commands
|
||||||
1
abschnitte/management/commands/__init__.py
Normal file
1
abschnitte/management/commands/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Commands package
|
||||||
23
abschnitte/management/commands/clear_diagram_cache.py
Normal file
23
abschnitte/management/commands/clear_diagram_cache.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from diagramm_proxy.diagram_cache import clear_cache
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Clear cached diagrams'
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
'--type',
|
||||||
|
type=str,
|
||||||
|
help='Diagram type to clear (e.g., plantuml, mermaid)',
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
diagram_type = options.get('type')
|
||||||
|
if diagram_type:
|
||||||
|
self.stdout.write(f'Clearing cache for {diagram_type}...')
|
||||||
|
clear_cache(diagram_type)
|
||||||
|
else:
|
||||||
|
self.stdout.write('Clearing all diagram caches...')
|
||||||
|
clear_cache()
|
||||||
|
self.stdout.write(self.style.SUCCESS('Cache cleared successfully'))
|
||||||
@@ -3,6 +3,10 @@ import base64
|
|||||||
import zlib
|
import zlib
|
||||||
import re
|
import re
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
# Import the caching function
|
||||||
|
from diagramm_proxy.diagram_cache import get_cached_diagram
|
||||||
|
|
||||||
DIAGRAMMSERVER="/diagramm"
|
DIAGRAMMSERVER="/diagramm"
|
||||||
|
|
||||||
@@ -25,15 +29,23 @@ def render_textabschnitte(queryset):
|
|||||||
elif typ == "tabelle":
|
elif typ == "tabelle":
|
||||||
html = md_table_to_html(inhalt)
|
html = md_table_to_html(inhalt)
|
||||||
elif typ == "diagramm":
|
elif typ == "diagramm":
|
||||||
temp=inhalt.splitlines()
|
temp = inhalt.splitlines()
|
||||||
diagramtype=temp.pop(0)
|
diagramtype = temp.pop(0)
|
||||||
diagramoptions='width="100%"'
|
diagramoptions = 'width="100%"'
|
||||||
if temp[0][0:6].lower() == "option":
|
if temp and temp[0][0:6].lower() == "option":
|
||||||
diagramoptions=temp.pop(0).split(":",1)[1]
|
diagramoptions = temp.pop(0).split(":", 1)[1]
|
||||||
rest="\n".join(temp)
|
rest = "\n".join(temp)
|
||||||
html = '<p><img '+diagramoptions+' src="'+DIAGRAMMSERVER+"/"+diagramtype+"/svg/"
|
|
||||||
html += base64.urlsafe_b64encode(zlib.compress(rest.encode("utf-8"),9)).decode()
|
# Use caching instead of URL encoding
|
||||||
html += '"></p>'
|
try:
|
||||||
|
cache_path = get_cached_diagram(diagramtype, rest)
|
||||||
|
# Generate URL to serve from media/static
|
||||||
|
diagram_url = settings.MEDIA_URL + cache_path
|
||||||
|
html = f'<p><img {diagramoptions} src="{diagram_url}"></p>'
|
||||||
|
except Exception as e:
|
||||||
|
# Fallback to error message
|
||||||
|
html = f'<p class="text-danger">Error generating diagram: {str(e)}</p>'
|
||||||
|
|
||||||
elif typ == "code":
|
elif typ == "code":
|
||||||
html = "<pre><code>"
|
html = "<pre><code>"
|
||||||
html += markdown(inhalt, extensions=['tables', 'attr_list'])
|
html += markdown(inhalt, extensions=['tables', 'attr_list'])
|
||||||
|
|||||||
@@ -18,36 +18,20 @@ spec:
|
|||||||
fsGroupChangePolicy: "OnRootMismatch"
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: loader
|
- name: loader
|
||||||
image: git.baumann.gr/adebaumann/vgui-data-loader:0.5
|
image: git.baumann.gr/adebaumann/vui-data-loader:0.8
|
||||||
command: [ "sh","-c","cp -n preload/preload.sqlite3 /data/db.sqlite3; chown -R 999:999 /data; ls -la /data; sleep 10; exit 0" ]
|
command: [ "sh","-c","cp preload/preload.sqlite3 /data/db.sqlite3; chown -R 999:999 /data; ls -la /data; sleep 10; exit 0" ]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: data
|
- name: data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
containers:
|
containers:
|
||||||
- name: web
|
- name: web
|
||||||
image: git.baumann.gr/adebaumann/vui:0.929
|
image: git.baumann.gr/adebaumann/vui:0.932
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8000
|
- containerPort: 8000
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: data
|
- name: data
|
||||||
mountPath: /app/data
|
mountPath: /app/data
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 2
|
|
||||||
failureThreshold: 6
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 20
|
|
||||||
periodSeconds: 20
|
|
||||||
timeoutSeconds: 2
|
|
||||||
failureThreshold: 3
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: data
|
- name: data
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
|
|||||||
Binary file not shown.
1
diagramm_proxy/__init__.py
Normal file
1
diagramm_proxy/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Diagram proxy module
|
||||||
91
diagramm_proxy/diagram_cache.py
Normal file
91
diagramm_proxy/diagram_cache.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from pathlib import Path
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.files.storage import default_storage
|
||||||
|
from django.core.files.base import ContentFile
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Configure cache directory
|
||||||
|
CACHE_DIR = getattr(settings, 'DIAGRAM_CACHE_DIR', 'diagram_cache')
|
||||||
|
KROKI_UPSTREAM = "http://svckroki:8000"
|
||||||
|
|
||||||
|
def get_cache_path(diagram_type, content_hash):
|
||||||
|
"""Generate cache file path for a diagram."""
|
||||||
|
return os.path.join(CACHE_DIR, diagram_type, f"{content_hash}.svg")
|
||||||
|
|
||||||
|
def compute_hash(content):
|
||||||
|
"""Compute SHA256 hash of diagram content."""
|
||||||
|
return hashlib.sha256(content.encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
|
def get_cached_diagram(diagram_type, diagram_content):
|
||||||
|
"""
|
||||||
|
Retrieve diagram from cache or generate it via POST.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
diagram_type: Type of diagram (e.g., 'plantuml', 'mermaid')
|
||||||
|
diagram_content: Raw diagram content
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path to cached diagram file (relative to MEDIA_ROOT)
|
||||||
|
"""
|
||||||
|
content_hash = compute_hash(diagram_content)
|
||||||
|
cache_path = get_cache_path(diagram_type, content_hash)
|
||||||
|
|
||||||
|
# Check if diagram exists in cache
|
||||||
|
if default_storage.exists(cache_path):
|
||||||
|
logger.debug(f"Cache hit for {diagram_type} diagram: {content_hash[:8]}")
|
||||||
|
return cache_path
|
||||||
|
|
||||||
|
# Generate diagram via POST request
|
||||||
|
logger.info(f"Cache miss for {diagram_type} diagram: {content_hash[:8]}, generating...")
|
||||||
|
try:
|
||||||
|
url = f"{KROKI_UPSTREAM}/{diagram_type}/svg"
|
||||||
|
response = requests.post(
|
||||||
|
url,
|
||||||
|
data=diagram_content.encode('utf-8'),
|
||||||
|
headers={'Content-Type': 'text/plain'},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# Ensure cache directory exists
|
||||||
|
cache_dir = os.path.dirname(default_storage.path(cache_path))
|
||||||
|
os.makedirs(cache_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# Save to cache
|
||||||
|
default_storage.save(cache_path, ContentFile(response.content))
|
||||||
|
logger.info(f"Diagram cached successfully: {cache_path}")
|
||||||
|
|
||||||
|
return cache_path
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
logger.error(f"Error generating diagram: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
def clear_cache(diagram_type=None):
|
||||||
|
"""
|
||||||
|
Clear cached diagrams.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
diagram_type: If specified, only clear diagrams of this type
|
||||||
|
"""
|
||||||
|
if diagram_type:
|
||||||
|
cache_path = os.path.join(CACHE_DIR, diagram_type)
|
||||||
|
else:
|
||||||
|
cache_path = CACHE_DIR
|
||||||
|
|
||||||
|
if default_storage.exists(cache_path):
|
||||||
|
full_path = default_storage.path(cache_path)
|
||||||
|
# Walk through and delete files
|
||||||
|
for root, dirs, files in os.walk(full_path):
|
||||||
|
for file in files:
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
try:
|
||||||
|
os.remove(file_path)
|
||||||
|
logger.info(f"Deleted cached diagram: {file_path}")
|
||||||
|
except OSError as e:
|
||||||
|
logger.error(f"Error deleting {file_path}: {e}")
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Standards Informatiksicherheit</h1>
|
<h1>Standards Informatiksicherheit</h1>
|
||||||
<ul>
|
<ul>
|
||||||
{% for standard in standards %}
|
{% for dokument in dokumente %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'standard_detail' nummer=standard.nummer %}">
|
<a href="{% url 'standard_detail' nummer=dokument.nummer %}">
|
||||||
{{ standard.nummer }} – {{ standard.name }}
|
{{ dokument.nummer }} – {{ dokument.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from myapp.models import Dokument
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
||||||
|
class DokumentTestCase (TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
Document.objects.create(name)
|
||||||
@@ -9,9 +9,9 @@ calendar=parsedatetime.Calendar()
|
|||||||
|
|
||||||
|
|
||||||
def standard_list(request):
|
def standard_list(request):
|
||||||
standards = Dokument.objects.all()
|
dokumente = Dokument.objects.all()
|
||||||
return render(request, 'standards/standard_list.html',
|
return render(request, 'standards/standard_list.html',
|
||||||
{'dokumente': standards}
|
{'dokumente': dokumente}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,6 @@
|
|||||||
<div class="flex-fill">{% block content %}Main Content{% endblock %}</div>
|
<div class="flex-fill">{% block content %}Main Content{% endblock %}</div>
|
||||||
<div class="col-md-2">{% block sidebar_right %}{% endblock %}</div>
|
<div class="col-md-2">{% block sidebar_right %}{% endblock %}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>VorgabenUI v0.927</div>
|
<div>VorgabenUI v0.931</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if resultat.kurztext %}
|
{% if resultat.all %}
|
||||||
<h2>Vorgaben mit "{{ suchbegriff }}" im Kurztext</h2>
|
<h2>Vorgaben mit "{{ suchbegriff }}"</h2>
|
||||||
{% for standard, vorgaben in resultat.kurztext.items %}
|
{% for standard, vorgaben in resultat.all.items %}
|
||||||
<h4>{{ standard }}</h4>
|
<h4>{{ standard }}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
{% for vorgabe in vorgaben %}
|
{% for vorgabe in vorgaben %}
|
||||||
@@ -24,18 +24,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if resultat.langtext %}
|
{% if not resultat.all %}
|
||||||
<h2>Vorgaben mit "{{ suchbegriff }}" im Langtext</h2>
|
|
||||||
{% for standard, vorgaben in resultat.langtext.items %}
|
|
||||||
<h4>{{ standard }}</h4>
|
|
||||||
<ul>
|
|
||||||
{% for vorgabe in vorgaben %}
|
|
||||||
<li><a href="{% url 'standard_detail' nummer=vorgabe.dokument.nummer %}#{{vorgabe.Vorgabennummer}}">{{vorgabe}}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% if not resultat.langtext and not resultat.kurztext and not resultat.geltungsbereich %}
|
|
||||||
<h2>Keine Resultate für "{{suchbegriff}}"</h2>
|
<h2>Keine Resultate für "{{suchbegriff}}"</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -15,27 +15,6 @@
|
|||||||
placeholder="Suchbegriff eingeben …"
|
placeholder="Suchbegriff eingeben …"
|
||||||
required>
|
required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Check-box group -->
|
|
||||||
<fieldset class="mb-4">
|
|
||||||
<legend class="h6 mb-2">In folgenden Bereichen suchen:</legend>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" value="kurztext" id="kurztext" name="suchbereich[]" checked>
|
|
||||||
<label class="form-check-label" for="kurztext">Kurztext</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" value="langtext" id="langtext" name="suchbereich[]" checked>
|
|
||||||
<label class="form-check-label" for="langtext">Langtext</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" value="geltungsbereich" id="geltungsbereich" name="suchbereich[]">
|
|
||||||
<label class="form-check-label" for="geltungsbereich">Geltungsbereich</label>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Suchen</button>
|
<button type="submit" class="btn btn-primary">Suchen</button>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from abschnitte.utils import render_textabschnitte
|
|||||||
from dokumente.models import Dokument, VorgabeLangtext, VorgabeKurztext, Geltungsbereich
|
from dokumente.models import Dokument, VorgabeLangtext, VorgabeKurztext, Geltungsbereich
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
import datetime
|
import datetime
|
||||||
|
import pprint
|
||||||
|
|
||||||
def startseite(request):
|
def startseite(request):
|
||||||
standards=list(Dokument.objects.all())
|
standards=list(Dokument.objects.all())
|
||||||
@@ -13,22 +14,18 @@ def search(request):
|
|||||||
return render(request, 'search.html')
|
return render(request, 'search.html')
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
suchbegriff=request.POST.get("q")
|
suchbegriff=request.POST.get("q")
|
||||||
areas=request.POST.getlist("suchbereich[]")
|
result= {"all": {}}
|
||||||
result= {}
|
qs = VorgabeKurztext.objects.filter(inhalt__contains=suchbegriff).exclude(abschnitt__gueltigkeit_bis__lt=datetime.date.today())
|
||||||
geltungsbereich=set()
|
result["kurztext"] = {k: [o.abschnitt for o in g] for k, g in groupby(qs, key=lambda o: o.abschnitt.dokument)}
|
||||||
if "kurztext" in areas:
|
qs = VorgabeLangtext.objects.filter(inhalt__contains=suchbegriff).exclude(abschnitt__gueltigkeit_bis__lt=datetime.date.today())
|
||||||
qs = VorgabeKurztext.objects.filter(inhalt__contains=suchbegriff).exclude(abschnitt__gueltigkeit_bis__lt=datetime.date.today())
|
result['langtext']= {k: [o.abschnitt for o in g] for k, g in groupby(qs, key=lambda o: o.abschnitt.dokument)}
|
||||||
result["kurztext"] = {k: [o.abschnitt for o in g] for k, g in groupby(qs, key=lambda o: o.abschnitt.dokument)}
|
|
||||||
if "langtext" in areas:
|
|
||||||
qs = VorgabeLangtext.objects.filter(inhalt__contains=suchbegriff).exclude(abschnitt__gueltigkeit_bis__lt=datetime.date.today())
|
|
||||||
result['langtext']= {k: [o.abschnitt for o in g] for k, g in groupby(qs, key=lambda o: o.abschnitt.dokument)}
|
|
||||||
if "geltungsbereich" in areas:
|
|
||||||
result["geltungsbereich"]={}
|
|
||||||
geltungsbereich=set(list([x.geltungsbereich for x in Geltungsbereich.objects.filter(inhalt__contains=suchbegriff)]))
|
|
||||||
for s in geltungsbereich:
|
|
||||||
result["geltungsbereich"][s]=render_textabschnitte(s.geltungsbereich_set.order_by("order"))
|
|
||||||
for r in result.keys():
|
for r in result.keys():
|
||||||
for s in result[r].keys():
|
for s in result[r].keys():
|
||||||
result[r][s]=set(result[r][s])
|
result["all"][s] = set(result[r][s])
|
||||||
|
result["geltungsbereich"]={}
|
||||||
|
geltungsbereich=set(list([x.geltungsbereich for x in Geltungsbereich.objects.filter(inhalt__contains=suchbegriff)]))
|
||||||
|
for s in geltungsbereich:
|
||||||
|
result["geltungsbereich"][s]=render_textabschnitte(s.geltungsbereich_set.order_by("order"))
|
||||||
|
pprint.pp (result)
|
||||||
return render(request,"results.html",{"suchbegriff":suchbegriff,"resultat":result})
|
return render(request,"results.html",{"suchbegriff":suchbegriff,"resultat":result})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user