Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions forum/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
20 changes: 1 addition & 19 deletions forum/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

from .markdown import MarkdownModel

import markdown
import bleach

# Create your models here.

class Item(MarkdownModel):
Expand Down Expand Up @@ -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:
Expand All @@ -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')
Expand Down
2 changes: 1 addition & 1 deletion forum/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions forum/templates/forum/collection_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

{% block content %}
<h1>{{ collection.name }}</h1>
{% if collection.description_html %}
<div class="markdown-body mb-3">{{ collection.description_html|safe }}</div>
{% if collection.content_html %}
<div class="markdown-body mb-3">{{ collection.content_html|safe }}</div>
{% endif %}

<p class="text-muted">
Expand Down
4 changes: 2 additions & 2 deletions forum/templates/forum/collection_form.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{% extends 'base.html' %}

{% block title %}{{ title }}{% endblock %}
{% block title %}创建合集{% endblock %}

{% block content %}
<h1>{{ title }}</h1>
<h1>创建合集</h1>

<form method="post" class="mt-3">
{% csrf_token %}
Expand Down
4 changes: 2 additions & 2 deletions forum/templates/forum/collection_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ <h1>合集</h1>
<div>
<a href="{% url 'collection_detail' collection.id %}">{{ collection.name }}</a>
<small class="text-muted ms-2">by {{ collection.owner.username }}</small>
{% if collection.description %}
<br><small class="text-muted">{{ collection.description }}</small>
{% if collection.content %}
<br><small class="text-muted">{{ collection.content | truncatechars:100}}</small>
{% endif %}
</div>
<span class="badge bg-secondary">{{ collection.collection_posts.count }} 篇</span>
Expand Down
10 changes: 5 additions & 5 deletions forum/templates/forum/post_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ <h1>所有文章</h1>
{% if item.type == 'collection' %}
<li>
<i class="bi bi-collection"></i>
<a href="{% url 'collection_detail' item.obj.id %}">{{ item.obj.name }}</a>
— 合集 · {{ item.obj.owner.username }}
· {{ item.obj.collection_posts.count }} 篇文章
<a href="{% url 'collection_detail' item.id %}">{{ item.name }}</a>
— 合集 · {{ item.owner.username }}
· {{ item.collection_posts.count }} 篇文章
</li>
{% else %}
<li>
{{ item.obj.title }} - 作者:{{ item.obj.author }} <small class="text-muted"><i class="bi bi-eye"></i> {{ item.obj.views }}</small>
<a href="{% url 'post_detail' item.obj.id %}">去查看</a>
{{ item.title }} - 作者:{{ item.author.username }} <small class="text-muted"><i class="bi bi-eye"></i> {{ item.views }}</small>
<a href="{% url 'post_detail' item.id %}">去查看</a>
</li>
{% endif %}
{% empty %}
Expand Down
57 changes: 39 additions & 18 deletions forum/views.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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):
Expand Down