new
All checks were successful
Deploy to Server / deploy (push) Successful in 36s

This commit is contained in:
jeremygan2021
2026-02-25 00:33:34 +08:00
parent 21f01fb0c4
commit 96c12b9e58
8 changed files with 71 additions and 20 deletions

View File

@@ -153,10 +153,11 @@ class TopicAdmin(ModelAdmin):
@admin.register(Reply)
class ReplyAdmin(ModelAdmin):
list_display = ('short_content', 'topic', 'author', 'created_at')
list_filter = ('created_at',)
list_display = ('short_content', 'topic', 'author', 'is_pinned', 'created_at')
list_filter = ('is_pinned', 'created_at')
search_fields = ('content', 'author__nickname', 'topic__title')
autocomplete_fields = ['author', 'topic', 'reply_to']
list_editable = ('is_pinned',)
inlines = [TopicMediaInline]
fieldsets = (
@@ -164,7 +165,7 @@ class ReplyAdmin(ModelAdmin):
'fields': ('topic', 'reply_to', 'content')
}),
('发布信息', {
'fields': ('author', 'created_at')
'fields': ('author', 'is_pinned', 'created_at')
}),
)
readonly_fields = ('created_at',)

View File

@@ -0,0 +1,22 @@
# Generated by Django 6.0.1 on 2026-02-24 16:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('community', '0012_activity_is_visible'),
]
operations = [
migrations.AlterModelOptions(
name='reply',
options={'ordering': ['-is_pinned', '-created_at'], 'verbose_name': '帖子回复', 'verbose_name_plural': '帖子回复管理'},
),
migrations.AddField(
model_name='reply',
name='is_pinned',
field=models.BooleanField(default=False, verbose_name='置顶'),
),
]

View File

@@ -186,6 +186,7 @@ class Reply(models.Model):
content = models.TextField(verbose_name="回复内容", help_text="支持Markdown格式")
author = models.ForeignKey(WeChatUser, on_delete=models.CASCADE, related_name='replies', verbose_name="回复者")
reply_to = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='children', verbose_name="回复楼层")
is_pinned = models.BooleanField(default=False, verbose_name="置顶")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="回复时间")
def __str__(self):
@@ -194,7 +195,7 @@ class Reply(models.Model):
class Meta:
verbose_name = "帖子回复"
verbose_name_plural = "帖子回复管理"
ordering = ['created_at']
ordering = ['-is_pinned', '-created_at']
class TopicMedia(models.Model):

View File

@@ -91,7 +91,7 @@ class ReplySerializer(serializers.ModelSerializer):
class Meta:
model = Reply
fields = ['id', 'topic', 'content', 'author', 'author_info', 'reply_to', 'media', 'created_at', 'media_ids']
fields = ['id', 'topic', 'content', 'author', 'author_info', 'reply_to', 'media', 'created_at', 'media_ids', 'is_pinned']
read_only_fields = ['author', 'created_at']
def create(self, validated_data):

View File

@@ -101,19 +101,7 @@ DATABASES = {
#从环境变量获取数据库配置 (Docker 环境会自动注入这些变量。
DB_HOST = os.environ.get('DB_HOST', '6.6.6.66')
if DB_HOST:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'market'),
'USER': os.environ.get('DB_USER', 'market'),
'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
'HOST': DB_HOST,
'PORT': os.environ.get('DB_PORT', '5432'),
}
# DB_HOST = os.environ.get('DB_HOST', '121.43.104.161')
# DB_HOST = os.environ.get('DB_HOST', '6.6.6.66')
# if DB_HOST:
# DATABASES['default'] = {
# 'ENGINE': 'django.db.backends.postgresql',
@@ -121,10 +109,22 @@ if DB_HOST:
# 'USER': os.environ.get('DB_USER', 'market'),
# 'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
# 'HOST': DB_HOST,
# 'PORT': os.environ.get('DB_PORT', '6433'),
# 'PORT': os.environ.get('DB_PORT', '5432'),
# }
DB_HOST = os.environ.get('DB_HOST', '121.43.104.161')
if DB_HOST:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'market'),
'USER': os.environ.get('DB_USER', 'market'),
'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
'HOST': DB_HOST,
'PORT': os.environ.get('DB_PORT', '6433'),
}
# Password validation
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators

View File

@@ -235,6 +235,29 @@ class VCCourseAdmin(OrderableAdminMixin, ModelAdmin):
list_display = ('title', 'course_type', 'price', 'tag', 'instructor', 'lesson_count', 'duration', 'created_at', 'order_actions')
search_fields = ('title', 'description', 'instructor', 'tag')
list_filter = ('course_type', 'instructor', 'tag')
actions = ['reset_ordering']
@admin.action(description="重置排序 (按ID顺序)")
def reset_ordering(self, request, queryset):
"""
将选中的课程或全部按ID顺序重新分配order值
"""
# 如果没有选中任何项默认处理所有Django Admin默认行为是选中了才会触发Action但为了稳健
# 这里既然是Action用户必须选中。建议用户选中所有。
# 为了方便如果用户只选了一个我们可以提示他选更多或者我们其实可以忽略queryset直接重置所有
# 通常Action是针对queryset的。
# 更好的做法对选中的queryset按ID排序然后更新order。
# 这种实现方式只重置选中的部分可能会导致order冲突。
# 稳妥方式:重置整个表的排序。
all_objects = VCCourse.objects.all().order_by('id')
for index, obj in enumerate(all_objects, start=1):
obj.order = index
obj.save(update_fields=['order'])
self.message_user(request, f"成功重置了 {all_objects.count()} 个课程的排序权重。")
fieldsets = (
('基本信息', {
'fields': ('title', 'description', 'course_type', 'tag', 'price')