diff --git a/gawa/blog/admin.py b/gawa/blog/admin.py index d976c95..7caa42b 100644 --- a/gawa/blog/admin.py +++ b/gawa/blog/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin +from django.utils.translation import gettext as _ from .models import * @admin.register(Category) @@ -7,6 +8,11 @@ class CategoryAdmin(admin.ModelAdmin): The admin model for Category """ +@admin.action(description=_("Regenerate searchable traits")) +def regenerate(modeladmin, request, queryset): + for obj in queryset: + obj.regenerate() + @admin.register(BlogPost) class BlogPostAdmin(admin.ModelAdmin): """ @@ -14,3 +20,5 @@ class BlogPostAdmin(admin.ModelAdmin): """ list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "date", "category", "slug", "suburl", "public"] date_hierarchy = "date" + ordering = ['title_de', 'title_en'] + actions = [regenerate] diff --git a/gawa/blog/migrations/0005_auto_20230604_0050.py b/gawa/blog/migrations/0005_auto_20230604_0050.py new file mode 100644 index 0000000..f831cf9 --- /dev/null +++ b/gawa/blog/migrations/0005_auto_20230604_0050.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.19 on 2023-06-03 22:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0004_blogpost_slug'), + ] + + operations = [ + migrations.AddField( + model_name='blogpost', + name='featured', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='blogpost', + name='thumbnail', + field=models.ImageField(blank=True, upload_to='img/thumbnails'), + ), + ] diff --git a/gawa/blog/migrations/0006_blogpost_markdown.py b/gawa/blog/migrations/0006_blogpost_markdown.py new file mode 100644 index 0000000..833d6ea --- /dev/null +++ b/gawa/blog/migrations/0006_blogpost_markdown.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.19 on 2023-06-03 22:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0005_auto_20230604_0050'), + ] + + operations = [ + migrations.AddField( + model_name='blogpost', + name='markdown', + field=models.BooleanField(default=False), + ), + ] diff --git a/gawa/blog/migrations/0007_remove_blogpost_public.py b/gawa/blog/migrations/0007_remove_blogpost_public.py new file mode 100644 index 0000000..220197b --- /dev/null +++ b/gawa/blog/migrations/0007_remove_blogpost_public.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.19 on 2023-06-03 23:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0006_blogpost_markdown'), + ] + + operations = [ + migrations.RemoveField( + model_name='blogpost', + name='public', + ), + ] diff --git a/gawa/blog/models.py b/gawa/blog/models.py index 0550fd3..b03d4d5 100644 --- a/gawa/blog/models.py +++ b/gawa/blog/models.py @@ -1,14 +1,27 @@ from django.db import models - +from django.utils.translation import gettext as _ from start.models import Searchable +import logging +logger = logging.getLogger(__name__) + class Category(models.Model): """ A category of blog posts + + Name not translated because it would make i18n in urls and Searchables specifically a pain. + Maybe some day it would be cool if these were Searchable """ - name = models.CharField(max_length=50) + name= models.CharField(max_length=50) slug = models.SlugField() + class Meta: + verbose_name = _("Category") + verbose_name_plural = _("Categories") + + def __str__(self): + return f"{{<{self.__class__.__name__}>\"{self.name}\"}}" + class BlogPost(Searchable): """ Should contain a blogpost @@ -16,5 +29,21 @@ class BlogPost(Searchable): body = models.TextField() category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True) thumbnail = models.ImageField(blank=True, upload_to="img/thumbnails") - public = models.BooleanField(default=True) + featured = models.BooleanField(default=False) + markdown = models.BooleanField(default=False) slug = models.SlugField() + + + def regenerate(self): + """ + regenerate a object + + Implements the abstract method of Searchable + """ + logger.info(f"regenerating {self.__class__.__name__} object: {self}") + self.suburl = f"/blog/{self.category.name}/{self.slug}" + self.save() + + class Meta: + verbose_name = _("blog post") + verbose_name_plural = _("blog posts") diff --git a/gawa/blog/templates/blog/featured.html b/gawa/blog/templates/blog/featured.html index f3de44c..0fd2484 100644 --- a/gawa/blog/templates/blog/featured.html +++ b/gawa/blog/templates/blog/featured.html @@ -2,6 +2,7 @@

{% trans "Featured" %}

+ {% for post in featured_posts %}
...
@@ -18,119 +19,6 @@ Another link
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
-
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
-
- ... -
-
Card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
- -
+ {% endfor %}
diff --git a/gawa/blog/views.py b/gawa/blog/views.py index baad3aa..f9090cb 100644 --- a/gawa/blog/views.py +++ b/gawa/blog/views.py @@ -6,7 +6,6 @@ from .models import BlogPost, Category from start.views import SearchableView import logging - logger = logging.getLogger(__name__) class Index(TemplateView, SearchableView): @@ -19,6 +18,12 @@ class Index(TemplateView, SearchableView): template_name: str = "blog/index.html" + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['featured_posts'] = BlogPost.objects.filter(featured=True, public=True) + logger.debug(f"loaded featured posts: {context['featured_posts']}") + return context + class Post(DetailView): """ Main page of a blog post @@ -28,6 +33,12 @@ class Post(DetailView): template_name = "blog/blogpost.html" context_object_name = "post" + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['featured_posts'] = BlogPost.objects.filter(featured=True) + logger.debug(f"loaded featured posts: {context['featured_posts']}") + return context + def get_object(self, queryset=None): obj = get_object_or_404( BlogPost, @@ -61,6 +72,12 @@ class CategoryList(ListView): template_name = "blog/categories.html" context_object_name = "categories" + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['featured_posts'] = BlogPost.objects.filter(featured=True) + logger.debug(f"loaded featured posts: {context['featured_posts']}") + return context + class ArticleList(ListView): """ Scroll through a list of blog posts @@ -72,3 +89,9 @@ class ArticleList(ListView): model=BlogPost template_name = "blog/posts.html" context_object_name = "posts" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['featured_posts'] = BlogPost.objects.filter(featured=True) + logger.debug(f"loaded featured posts: {context['featured_posts']}") + return context diff --git a/gawa/migrate.sh b/gawa/migrate.sh new file mode 100755 index 0000000..1926a10 --- /dev/null +++ b/gawa/migrate.sh @@ -0,0 +1,2 @@ +#!/bin/bash +python manage.py makemigrations && python manage.py migrate diff --git a/gawa/start/admin.py b/gawa/start/admin.py index 4a31d70..7cb02d1 100644 --- a/gawa/start/admin.py +++ b/gawa/start/admin.py @@ -1,8 +1,15 @@ from django.contrib import admin from django.db.models import CASCADE, AutoField, OneToOneField from django.views.generic import View +from django.utils.translation import gettext as _ from .models import * + +@admin.action(description=_("Regenerate searchable traits")) +def regenerate(modeladmin, request, queryset): + for obj in queryset: + obj.regenerate() + @admin.register(Keyword) class KeywordAdmin(admin.ModelAdmin): """ @@ -16,3 +23,5 @@ class StaticSiteAdmin(admin.ModelAdmin): Admin Interface for StaticSite """ list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "suburl"] + ordering = ['title_de', 'title_en'] + actions = [regenerate] diff --git a/gawa/start/apps.py b/gawa/start/apps.py index 9f48da5..7ec3c85 100644 --- a/gawa/start/apps.py +++ b/gawa/start/apps.py @@ -1,6 +1,5 @@ from django.apps import AppConfig - class StartConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'start' diff --git a/gawa/start/migrations/0003_searchable_public.py b/gawa/start/migrations/0003_searchable_public.py new file mode 100644 index 0000000..a923f0c --- /dev/null +++ b/gawa/start/migrations/0003_searchable_public.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.19 on 2023-06-03 23:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('start', '0002_keyword_searchable_staticsite'), + ] + + operations = [ + migrations.AddField( + model_name='searchable', + name='public', + field=models.BooleanField(default=True), + ), + ] diff --git a/gawa/start/models.py b/gawa/start/models.py index 3037556..cec0708 100644 --- a/gawa/start/models.py +++ b/gawa/start/models.py @@ -1,8 +1,8 @@ from django.db import models from django.db.models.options import override -#from .views import SearchableView -# ^^^ raises Circular Import +import logging +logger = logging.getLogger(__name__) class Keyword(models.Model): """ @@ -11,6 +11,9 @@ class Keyword(models.Model): text_de = models.CharField(max_length=40) text_en = models.CharField(max_length=40) + def __str__(self): + return f"{{<{self.__class__.__name__}>\"{self.text_en}\"}}" + class Searchable(models.Model): """ Abstract class for any model that should be searchable. @@ -28,13 +31,25 @@ class Searchable(models.Model): date = models.DateField(blank=True, null=True) keywords = models.ManyToManyField(Keyword) suburl = models.CharField(max_length=200, blank=True, null=True) + public = models.BooleanField(default=True) @classmethod def regenerate_all_entries(cls): """ regenerate all searchable items """ - raise NotImplementedError + logger.info(f"regenerating all {Searchable.__name__} entries") + for obj in cls.objects.all(): + obj.regenerate() + + def __str__(self): + return f"{{<{self.__class__.__name__}>\"{self.title_en}\"}}" + + def regenerate(self): + """ + regenerate a object + """ + raise NotImplementedError("This model does not implement regenerate") class StaticSite(Searchable): """ @@ -54,4 +69,4 @@ class StaticSite(Searchable): # TODO automate searching for these #all_views: list[SearchableView] = [] - raise NotImplementedError + raise NotImplementedError("This model does not implement regenerate_all_entries") diff --git a/gawa/start/views.py b/gawa/start/views.py index c2953df..a0fd0bc 100644 --- a/gawa/start/views.py +++ b/gawa/start/views.py @@ -85,6 +85,7 @@ class MainSearch(ListView): Q(subtitle_de__icontains=search) | Q(subtitle_en__icontains=search) | Q(desc_de__icontains=search) | Q(desc_en__icontains=search) ) + object_list = object_list.filter(public=True) print(object_list) return object_list diff --git a/gawa/thumbnails/thuglifemathemann.png b/gawa/thumbnails/thuglifemathemann.png deleted file mode 100644 index a6daad6..0000000 Binary files a/gawa/thumbnails/thuglifemathemann.png and /dev/null differ