blog-markdown #31
|
@ -11,6 +11,8 @@ https://docs.djangoproject.com/en/3.2/ref/settings/
|
|||
"""
|
||||
|
||||
# for getting envvars
|
||||
import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import os
|
||||
|
||||
# default django
|
||||
|
@ -35,7 +37,7 @@ ALLOWED_HOSTS = ["*"]
|
|||
|
||||
# Allow inclusion of stuff from these origins
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
"https://static.cscherr.de",
|
||||
"https://static.cscherr.de",
|
||||
]
|
||||
|
||||
# Application definition
|
||||
|
@ -100,7 +102,6 @@ DATABASES = {
|
|||
}
|
||||
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||
|
||||
|
@ -123,7 +124,6 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/3.2/topics/i18n/
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
LANGUAGES = [
|
||||
("de", _("German")),
|
||||
|
@ -155,10 +155,10 @@ STATIC_URL = '/static/'
|
|||
COMPRESS_ENABLED = True
|
||||
|
||||
STATICFILES_FINDERS = [
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
]
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
]
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/x-scss', 'django_libsass.SassCompiler'),
|
||||
|
@ -173,7 +173,6 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||
|
||||
# Logging configs
|
||||
|
||||
import logging
|
||||
|
||||
myServerFormatter = ServerFormatter
|
||||
myServerFormatter.default_time_format = "%Y-%M-%d %H:%M:%S"
|
||||
|
@ -294,7 +293,7 @@ LOGGING = {
|
|||
# Media stuff
|
||||
# this is where user uploaded files will go.
|
||||
# TODO change this for prod
|
||||
#MEDIA_ROOT = "/home/plex/Documents/code/python/gawa/media"
|
||||
# MEDIA_ROOT = "/home/plex/Documents/code/python/gawa/media"
|
||||
MEDIA_ROOT = "/app/media"
|
||||
MEDIA_URL = "/media/"
|
||||
# FILE_UPLOAD_TEMP_DIR = "/tmp/gawa/upload"
|
||||
|
|
|
@ -21,7 +21,7 @@ from django.conf import settings
|
|||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
re_path(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
|
|
|
@ -10,6 +10,7 @@ def regenerate(modeladmin, request, queryset):
|
|||
for obj in queryset:
|
||||
obj.regenerate()
|
||||
|
||||
|
||||
@admin.register(Keyword)
|
||||
class KeywordAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
|
@ -17,21 +18,25 @@ class KeywordAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
list_display = ["text_en", "text_de"]
|
||||
|
||||
|
||||
@admin.register(StaticSite)
|
||||
class StaticSiteAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin Interface for StaticSite
|
||||
"""
|
||||
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "suburl"]
|
||||
list_display = ["title_en", "subtitle_en",
|
||||
"title_de", "subtitle_de", "suburl"]
|
||||
ordering = ['title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
||||
|
||||
@admin.register(Searchable)
|
||||
class SearchableAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Abstract Admin Interface for all Searchables
|
||||
"""
|
||||
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "suburl"]
|
||||
list_display = ["title_en", "subtitle_en",
|
||||
"title_de", "subtitle_de", "suburl"]
|
||||
ordering = ['title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
||||
|
@ -41,6 +46,7 @@ class LinkAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
Admin Interface for Links
|
||||
"""
|
||||
list_display = ["title_en", "title_de", "url", "suburl", "favicon", "status", "personal"]
|
||||
list_display = ["title_en", "title_de", "url",
|
||||
"suburl", "favicon", "status", "personal"]
|
||||
ordering = ['status', 'title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class StartConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'start'
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
class MainSearchForm(forms.Form):
|
||||
search = forms.CharField(
|
||||
max_length=100,
|
||||
label=''
|
||||
max_length=100,
|
||||
label=''
|
||||
)
|
||||
search.widget = forms.TextInput(
|
||||
attrs={
|
||||
|
|
|
@ -15,7 +15,8 @@ class LangBasedOnUrlMiddleware(MiddlewareMixin):
|
|||
def process_request(request):
|
||||
|
||||
if hasattr(request, 'session'):
|
||||
active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)
|
||||
active_session_lang = request.session.get(
|
||||
translation.LANGUAGE_SESSION_KEY)
|
||||
|
||||
if active_session_lang == request.LANGUAGE_CODE:
|
||||
return
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import random
|
||||
import favicon
|
||||
import requests
|
||||
from django.db import models
|
||||
from django.db.models.options import override
|
||||
from django.utils.translation import gettext as _
|
||||
|
@ -8,9 +11,6 @@ from django.conf import settings
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import requests
|
||||
import favicon
|
||||
import random
|
||||
|
||||
class Keyword(models.Model):
|
||||
"""
|
||||
|
@ -26,6 +26,7 @@ class Keyword(models.Model):
|
|||
verbose_name = _("Keyword")
|
||||
verbose_name_plural = _("keywords")
|
||||
|
||||
|
||||
class Searchable(models.Model):
|
||||
"""
|
||||
Abstract class for any model that should be searchable.
|
||||
|
@ -37,8 +38,10 @@ class Searchable(models.Model):
|
|||
title_en = models.CharField(max_length=50, default="title EN")
|
||||
subtitle_de = models.CharField(max_length=50, blank=True)
|
||||
subtitle_en = models.CharField(max_length=50, blank=True)
|
||||
desc_de = models.TextField(blank=True, max_length=250, unique=False, default="Beschreibung DE")
|
||||
desc_en = models.TextField(blank=True, max_length=250, unique=False, default="Description EN")
|
||||
desc_de = models.TextField(
|
||||
blank=True, max_length=250, unique=False, default="Beschreibung DE")
|
||||
desc_en = models.TextField(
|
||||
blank=True, max_length=250, unique=False, default="Description EN")
|
||||
# may be empty/blank for some entries
|
||||
date = models.DateField(blank=True, null=True)
|
||||
keywords = models.ManyToManyField(Keyword)
|
||||
|
@ -61,12 +64,14 @@ class Searchable(models.Model):
|
|||
"""
|
||||
regenerate a object
|
||||
"""
|
||||
raise NotImplementedError(f"{self.__class__.__name__} does not implement regenerate")
|
||||
raise NotImplementedError(
|
||||
f"{self.__class__.__name__} does not implement regenerate")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Searchable")
|
||||
verbose_name_plural = _("Searchables")
|
||||
|
||||
|
||||
class StaticSite(Searchable):
|
||||
"""
|
||||
This model represents any static site, such as start:index,
|
||||
|
@ -75,20 +80,21 @@ class StaticSite(Searchable):
|
|||
Every searchable view should inherit from start.views.SearchableView.
|
||||
# TODO automate scanning for SearchableView classes
|
||||
"""
|
||||
|
||||
|
||||
def regenerate(self):
|
||||
"""
|
||||
regenerate a object
|
||||
"""
|
||||
logger.info(f"regenerating {self.__class__.__name__} object: {self}")
|
||||
logger.warning(f"{self.__class__.__name__} cannot regenerate.")
|
||||
#self.save()
|
||||
# self.save()
|
||||
pass
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("static site")
|
||||
verbose_name_plural = _("static sites")
|
||||
|
||||
|
||||
class Link(Searchable):
|
||||
"""
|
||||
contains all my interesting links
|
||||
|
@ -121,11 +127,13 @@ class Link(Searchable):
|
|||
icons = favicon.get(self.url, timeout=2)
|
||||
except (ConnectionError) as ce:
|
||||
# just keep whatever was stored if we cant get a new favicon
|
||||
logger.warn(f"unable to download favicon for {self}: {ce.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"unable to download favicon for {self}: {ce.with_traceback(None)}")
|
||||
self.status = False
|
||||
|
||||
except Exception as e:
|
||||
logger.warn(f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
self.status = False
|
||||
|
||||
else:
|
||||
|
@ -144,9 +152,10 @@ class Link(Searchable):
|
|||
except FileNotFoundError as fe:
|
||||
logger.error(f"cant write favicon to file for {self}: {fe}")
|
||||
self.favicon = None
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.warn(f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
self.favicon = None
|
||||
|
||||
self.save()
|
||||
|
|
|
@ -36,4 +36,3 @@ def change_lang(context, lang="de", *args, **kwargs):
|
|||
finally:
|
||||
activate(lang)
|
||||
return "%s" % url
|
||||
|
||||
|
|
|
@ -9,5 +9,6 @@ urlpatterns = [
|
|||
path("legal/", views.LegalInfo.as_view(), name="legal"),
|
||||
path("links/", views.Links.as_view(), name="links"),
|
||||
path("professional/", views.LegalInfo.as_view(), name="professional"),
|
||||
path('language/activate/<language_code>/', views.ActivateLanguage.as_view(), name='activate_language'),
|
||||
path('language/activate/<language_code>/',
|
||||
views.ActivateLanguage.as_view(), name='activate_language'),
|
||||
]
|
||||
|
|
|
@ -18,6 +18,7 @@ from abc import ABC
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SearchableView(View, ABC):
|
||||
"""
|
||||
This abstract view implements some traits of views that should show up
|
||||
|
@ -40,6 +41,7 @@ class Index(TemplateView, SearchableView):
|
|||
|
||||
template_name: str = "start/index.html"
|
||||
|
||||
|
||||
class Professional(TemplateView, SearchableView):
|
||||
"""
|
||||
Professional informations that might interest a professional employer
|
||||
|
@ -47,6 +49,7 @@ class Professional(TemplateView, SearchableView):
|
|||
# TODO
|
||||
template_name: str = "start/legalinfo.html"
|
||||
|
||||
|
||||
class LegalInfo(TemplateView, SearchableView):
|
||||
"""
|
||||
Legal info that the german authorities want.
|
||||
|
@ -54,20 +57,22 @@ class LegalInfo(TemplateView, SearchableView):
|
|||
# TODO
|
||||
template_name: str = "start/legalinfo.html"
|
||||
|
||||
|
||||
class ActivateLanguage(View):
|
||||
"""
|
||||
Set the language to whatever
|
||||
"""
|
||||
language_code = ''
|
||||
redirect_to = ''
|
||||
redirect_to = ''
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.redirect_to = request.META.get('HTTP_REFERER')
|
||||
self.redirect_to = request.META.get('HTTP_REFERER')
|
||||
self.language_code = kwargs.get('language_code')
|
||||
translation.activate(self.language_code)
|
||||
request.session[translation.LANGUAGE_SESSION_KEY] = self.language_code
|
||||
return redirect(self.redirect_to)
|
||||
|
||||
|
||||
class MainSearch(ListView):
|
||||
"""
|
||||
Search for anything.
|
||||
|
@ -94,6 +99,7 @@ class MainSearch(ListView):
|
|||
return render(request, "errors/bad_request.html")
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class Links(ListView):
|
||||
"""
|
||||
This View contains links to various interesting sites.
|
||||
|
@ -115,6 +121,6 @@ class Links(ListView):
|
|||
return object_list
|
||||
|
||||
def get_context_data(self, *, object_list=None, **kwargs):
|
||||
context = super().get_context_data(object_list=object_list, **kwargs)
|
||||
context = super().get_context_data(object_list=object_list, **kwargs)
|
||||
context['personal_links'] = self.get_queryset_personal_links()
|
||||
return context
|
||||
|
|
Loading…
Reference in New Issue