diff --git a/forum/form.py b/forum/form.py index 05ff949..001e88d 100644 --- a/forum/form.py +++ b/forum/form.py @@ -37,14 +37,14 @@ def __init__(self, *args, user=None, **kwargs): class Meta: model = Collection - fields = ['name', 'description'] + fields = ['name', 'content'] labels = { 'name': '合集名称', - 'description': '描述', + 'content': '描述', } widgets = { 'name': forms.TextInput(attrs={'class': 'form-control'}), - 'description': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), + 'content': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), } def save(self, commit=True): diff --git a/forum/models.py b/forum/models.py index 0880d48..d9e5afd 100644 --- a/forum/models.py +++ b/forum/models.py @@ -3,9 +3,6 @@ from .markdown import MarkdownModel -import markdown -import bleach - # Create your models here. class Item(MarkdownModel): @@ -47,11 +44,9 @@ def __str__(self): return f"{self.author} comment {self.post}" -class Collection(models.Model): +class Collection(MarkdownModel): owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='collections') name = models.CharField(max_length=100) - description = models.TextField(blank=True, default='') - description_html = models.TextField(editable=False, blank=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: @@ -60,19 +55,6 @@ class Meta: def __str__(self): return self.name - def save(self, *args, **kwargs): - if self.description: - html = markdown.markdown(self.description, extensions=MarkdownModel.MARKDOWN_EXTENSIONS) - self.description_html = bleach.clean( - html, - tags=MarkdownModel.allowed_tags, - attributes=MarkdownModel.allowed_attrs, - protocols=MarkdownModel.ALLOWED_PROTOCOLS, - ) - else: - self.description_html = '' - super().save(*args, **kwargs) - class CollectionPost(models.Model): collection = models.ForeignKey(Collection, on_delete=models.CASCADE, related_name='collection_posts') diff --git a/forum/templates/base.html b/forum/templates/base.html index cec2719..76a6596 100644 --- a/forum/templates/base.html +++ b/forum/templates/base.html @@ -122,7 +122,7 @@ function updateThemeIcon() { const icon = document.getElementById('theme-icon'); const isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark'; - icon.className = 'bi ' + (isDark ? 'bi-sun' : 'bi-moon-stars'); + icon.className = 'bi ' + (isDark ? 'bi-moon' : 'bi-sun'); } updateThemeIcon(); diff --git a/forum/templates/forum/collection_detail.html b/forum/templates/forum/collection_detail.html index 465b31f..e460b55 100644 --- a/forum/templates/forum/collection_detail.html +++ b/forum/templates/forum/collection_detail.html @@ -4,8 +4,8 @@ {% block content %}

{{ collection.name }}

-{% if collection.description_html %} -
{{ collection.description_html|safe }}
+{% if collection.content_html %} +
{{ collection.content_html|safe }}
{% endif %}

diff --git a/forum/templates/forum/collection_form.html b/forum/templates/forum/collection_form.html index 7a483bb..86118f6 100644 --- a/forum/templates/forum/collection_form.html +++ b/forum/templates/forum/collection_form.html @@ -1,9 +1,9 @@ {% extends 'base.html' %} -{% block title %}{{ title }}{% endblock %} +{% block title %}创建合集{% endblock %} {% block content %} -

{{ title }}

+

创建合集

{% csrf_token %} diff --git a/forum/templates/forum/collection_list.html b/forum/templates/forum/collection_list.html index 9e9c854..d7d8769 100644 --- a/forum/templates/forum/collection_list.html +++ b/forum/templates/forum/collection_list.html @@ -14,8 +14,8 @@

合集

{{ collection.name }} by {{ collection.owner.username }} - {% if collection.description %} -
{{ collection.description }} + {% if collection.content %} +
{{ collection.content | truncatechars:100}} {% endif %}
{{ collection.collection_posts.count }} 篇 diff --git a/forum/templates/forum/post_list.html b/forum/templates/forum/post_list.html index 8b0d24b..a5bc6a9 100644 --- a/forum/templates/forum/post_list.html +++ b/forum/templates/forum/post_list.html @@ -10,14 +10,14 @@

所有文章

{% if item.type == 'collection' %}
  • - {{ item.obj.name }} - — 合集 · {{ item.obj.owner.username }} - · {{ item.obj.collection_posts.count }} 篇文章 + {{ item.name }} + — 合集 · {{ item.owner.username }} + · {{ item.collection_posts.count }} 篇文章
  • {% else %}
  • - {{ item.obj.title }} - 作者:{{ item.obj.author }} {{ item.obj.views }} - 去查看 + {{ item.title }} - 作者:{{ item.author.username }} {{ item.views }} + 去查看
  • {% endif %} {% empty %} diff --git a/forum/views.py b/forum/views.py index 1c08d7b..c67d138 100644 --- a/forum/views.py +++ b/forum/views.py @@ -1,5 +1,5 @@ import json, re, random -from django.db.models import F +from django.db.models import F, CharField, Subquery, Value from django.db import models as db_models from django.http import JsonResponse from django.urls import reverse_lazy @@ -22,30 +22,51 @@ def index(request): items = Item.objects.all() - posts = Post.objects.all().order_by('-created_at')[:5] + posts = Post.objects.all()[:5] return render(request, 'forum/index.html', {'items': items, 'posts' : posts}) def post_list(request): - # IDs of posts that belong to any collection - collected_post_ids = CollectionPost.objects.values_list('post_id', flat=True) - # Standalone posts (not in any collection) - standalone_posts = [ - {'type': 'post', 'obj': p, 'date': p.created_at} - for p in Post.objects.exclude(id__in=collected_post_ids) - ] + standalone_posts = Post.objects.exclude( + id__in = CollectionPost.objects.values_list('post_id', flat=True) # IDs of posts that belong to any collection + ).annotate( + type=Value('post', output_field=CharField()) + ).values("type", "id", "created_at").order_by() # Collections as items - collection_items = [ - {'type': 'collection', 'obj': c, 'date': c.created_at} - for c in Collection.objects.all() - ] + collection_items = Collection.objects.annotate( + type=Value('collection', output_field=CharField()) + ).values("type", "id", "created_at").order_by() + + combined = standalone_posts.union( + collection_items, + all=True + ).order_by('-created_at') + + paginator = Paginator(combined, 20) + page_items = paginator.get_page(request.GET.get('page', 1)) + + page_post_ids = [] + page_collection_ids = [] + for row in page_items: + if row["type"] == "post": + page_post_ids.append(row["id"]) + else: + page_collection_ids.append(row["id"]) + + posts = Post.objects.in_bulk(page_post_ids) + collections = Collection.objects.in_bulk(page_collection_ids) - # Merge and sort by date descending - items = sorted(standalone_posts + collection_items, key=lambda x: x['date'], reverse=True) - paginator = Paginator(items, 20) - page_obj = paginator.get_page(request.GET.get('page', 1)) + page_obj = [] + for row in page_items: + if row["type"] == "post": + obj = posts.get(row["id"]) + else: + obj = collections.get(row["id"]) + + obj.type = row["type"] + page_obj.append(obj) return render(request, 'forum/post_list.html', { 'page_obj': page_obj, @@ -254,7 +275,7 @@ def collection_create(request): if form.is_valid(): form.save() return redirect('collection_list') - return render(request, 'forum/collection_form.html', {'form': form, 'title': '创建合集'}) + return render(request, 'forum/collection_form.html', {'form': form}) def collection_detail(request, collection_id):