feat: 多用户系统改造(数据模型 + 认证 API)

This commit is contained in:
maoshen
2026-04-15 02:59:36 +00:00
parent 75423d4e0e
commit e6aecd2752
13 changed files with 283 additions and 13 deletions

View File

@@ -0,0 +1,54 @@
# Generated by Django 4.2.11 on 2026-04-15 02:59
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('diary', '0007_comment_creativity_comment_efficiency_and_more'),
]
operations = [
migrations.RemoveField(
model_name='comment',
name='created_by',
),
migrations.AddField(
model_name='comment',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='创建者'),
),
migrations.AddField(
model_name='diaryentry',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='diary_entries', to=settings.AUTH_USER_MODEL, verbose_name='用户'),
),
migrations.AddField(
model_name='experience',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='experiences', to=settings.AUTH_USER_MODEL, verbose_name='用户'),
),
migrations.AddField(
model_name='task',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to=settings.AUTH_USER_MODEL, verbose_name='创建者'),
),
migrations.AlterField(
model_name='diaryentry',
name='date',
field=models.DateField(verbose_name='日期'),
),
migrations.AlterField(
model_name='task',
name='assigned_to',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_tasks', to=settings.AUTH_USER_MODEL, verbose_name='负责人'),
),
migrations.AlterUniqueTogether(
name='diaryentry',
unique_together={('user', 'date')},
),
]

View File

@@ -1,5 +1,6 @@
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class DiaryEntry(models.Model):
"""
@@ -16,7 +17,8 @@ class DiaryEntry(models.Model):
2. 确认不影响日历显示
3. 运行 test_frontend.py diary 验证
"""
date = models.DateField('日期', unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户', related_name='diary_entries', null=True, blank=True)
date = models.DateField('日期')
title = models.CharField('标题', max_length=200, default='每日日记')
content = models.TextField('日记内容', blank=True, default='')
completed_tasks = models.TextField('完成的任务', blank=True, default='')
@@ -35,6 +37,7 @@ class DiaryEntry(models.Model):
ordering = ['-date']
verbose_name = '日记'
verbose_name_plural = '日记'
unique_together = ['user', 'date'] # 每个用户每天一条日记
def __str__(self):
return f"{self.date} - {self.title}"
@@ -70,6 +73,7 @@ class Experience(models.Model):
修改前阅读 docs/EXPERIENCE.md
"""
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户', related_name='experiences', null=True, blank=True)
title = models.CharField('标题', max_length=200)
category = models.CharField('类别', max_length=50, choices=[
('deployment', '📦 部署'),
@@ -134,7 +138,7 @@ class Comment(models.Model):
creativity = models.IntegerField('创新性', null=True, blank=True, help_text='1-10 分')
learning = models.IntegerField('学习价值', null=True, blank=True, help_text='1-10 分')
created_by = models.CharField('创建者', max_length=100, default='北极星')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='创建者', related_name='comments', null=True, blank=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
class Meta:
@@ -169,7 +173,8 @@ class Task(models.Model):
priority = models.CharField('优先级', max_length=20, choices=PRIORITY_CHOICES, default='medium')
progress_percent = models.IntegerField('进展百分比', default=0)
progress_notes = models.TextField('进展记录', blank=True, default='')
assigned_to = models.CharField('负责人', max_length=100, blank=True, default='码神')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='创建者', related_name='tasks', null=True, blank=True)
assigned_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='负责人', related_name='assigned_tasks')
due_date = models.DateField('截止日期', null=True, blank=True)
completed_at = models.DateTimeField('完成时间', null=True, blank=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)

View File

@@ -3,11 +3,11 @@ from rest_framework.routers import DefaultRouter
from .views import DiaryEntryViewSet, DailyProgressViewSet, ExperienceViewSet, TaskViewSet, CommentViewSet
router = DefaultRouter()
router.register(r'entries', DiaryEntryViewSet)
router.register(r'progress', DailyProgressViewSet)
router.register(r'experiences', ExperienceViewSet)
router.register(r'tasks', TaskViewSet)
router.register(r'comments', CommentViewSet)
router.register(r'entries', DiaryEntryViewSet, basename='diaryentry')
router.register(r'progress', DailyProgressViewSet, basename='dailyprogress')
router.register(r'experiences', ExperienceViewSet, basename='experience')
router.register(r'tasks', TaskViewSet, basename='task')
router.register(r'comments', CommentViewSet, basename='comment')
urlpatterns = [
path('', include(router.urls)),

View File

@@ -1,6 +1,7 @@
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions
from django.utils import timezone
from .models import DiaryEntry, DailyProgress, Experience, Task, Comment
from .serializers import (
@@ -9,21 +10,24 @@ from .serializers import (
)
class DiaryEntryViewSet(viewsets.ModelViewSet):
queryset = DiaryEntry.objects.all()
serializer_class = DiaryEntrySerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return DiaryEntry.objects.filter(user=self.request.user)
@action(detail=False, methods=['get'])
def today(self, request):
"""获取今天的日记"""
today = timezone.now().date()
entry, created = DiaryEntry.objects.get_or_create(date=today)
entry, created = DiaryEntry.objects.get_or_create(user=request.user, date=today)
serializer = self.get_serializer(entry)
return Response(serializer.data)
@action(detail=False, methods=['get'])
def recent(self, request):
"""获取最近 7 天的日记"""
entries = DiaryEntry.objects.order_by('-date')[:7]
entries = DiaryEntry.objects.filter(user=request.user).order_by('-date')[:7]
serializer = self.get_serializer(entries, many=True)
return Response(serializer.data)
@@ -73,8 +77,11 @@ class DailyProgressViewSet(viewsets.ModelViewSet):
class ExperienceViewSet(viewsets.ModelViewSet):
queryset = Experience.objects.all()
serializer_class = ExperienceSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Experience.objects.filter(user=self.request.user)
@action(detail=False, methods=['get'])
def by_category(self, request):
@@ -96,8 +103,11 @@ class ExperienceViewSet(viewsets.ModelViewSet):
class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all()
serializer_class = TaskSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Task.objects.filter(user=self.request.user)
@action(detail=False, methods=['get'])
def by_status(self, request):