regeneration for blogposts

This commit is contained in:
Christoph J. Scherr 2023-06-04 01:53:21 +02:00
parent 08c26ce090
commit 91667a7da9
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
14 changed files with 173 additions and 123 deletions

View File

@ -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]

View File

@ -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'),
),
]

View File

@ -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),
),
]

View File

@ -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',
),
]

View File

@ -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)
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")

View File

@ -2,6 +2,7 @@
<div class="container-lg mt-5">
<h4 class="">{% trans "Featured" %}</h4>
<div class="row my-4">
{% for post in featured_posts %}
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
@ -18,119 +19,6 @@
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
</div>
<div class="row my-4">
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
<div class="card mx-3" style="width: 18rem;">
<img src="https://static.cscherr.de/images/profile/profile-margin-downscaled.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<div class="card-body">
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
{% endfor %}
</div>
</div>

View File

@ -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

2
gawa/migrate.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
python manage.py makemigrations && python manage.py migrate

View File

@ -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]

View File

@ -1,6 +1,5 @@
from django.apps import AppConfig
class StartConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'start'

View File

@ -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),
),
]

View File

@ -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")

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB