@ -0,0 +1,3 @@ | |||
from django.contrib import admin | |||
# Register your models here. |
@ -0,0 +1,6 @@ | |||
from django.apps import AppConfig | |||
class CommunityConfig(AppConfig): | |||
default_auto_field = "django.db.models.BigAutoField" | |||
name = "Community" |
@ -0,0 +1,86 @@ | |||
# Generated by Django 5.2 on 2025-05-30 01:17 | |||
from django.db import migrations, models | |||
class Migration(migrations.Migration): | |||
initial = True | |||
dependencies = [] | |||
operations = [ | |||
migrations.CreateModel( | |||
name="Comment", | |||
fields=[ | |||
( | |||
"id", | |||
models.BigAutoField( | |||
auto_created=True, | |||
primary_key=True, | |||
serialize=False, | |||
verbose_name="ID", | |||
), | |||
), | |||
("content", models.TextField()), | |||
("created_at", models.DateTimeField(auto_now_add=True)), | |||
], | |||
), | |||
migrations.CreateModel( | |||
name="Favorite", | |||
fields=[ | |||
( | |||
"id", | |||
models.BigAutoField( | |||
auto_created=True, | |||
primary_key=True, | |||
serialize=False, | |||
verbose_name="ID", | |||
), | |||
), | |||
("created_at", models.DateTimeField(auto_now_add=True)), | |||
], | |||
), | |||
migrations.CreateModel( | |||
name="Like", | |||
fields=[ | |||
( | |||
"id", | |||
models.BigAutoField( | |||
auto_created=True, | |||
primary_key=True, | |||
serialize=False, | |||
verbose_name="ID", | |||
), | |||
), | |||
("created_at", models.DateTimeField(auto_now_add=True)), | |||
], | |||
), | |||
migrations.CreateModel( | |||
name="Post", | |||
fields=[ | |||
( | |||
"id", | |||
models.BigAutoField( | |||
auto_created=True, | |||
primary_key=True, | |||
serialize=False, | |||
verbose_name="ID", | |||
), | |||
), | |||
("content", models.TextField(verbose_name="内容")), | |||
( | |||
"image", | |||
models.ImageField(blank=True, null=True, upload_to="post_images/"), | |||
), | |||
( | |||
"video", | |||
models.FileField(blank=True, null=True, upload_to="post_videos/"), | |||
), | |||
("like_count", models.PositiveIntegerField(default=0)), | |||
("comment_count", models.PositiveIntegerField(default=0)), | |||
("favorite_count", models.PositiveIntegerField(default=0)), | |||
("created_at", models.DateTimeField(auto_now_add=True)), | |||
], | |||
), | |||
] |
@ -0,0 +1,67 @@ | |||
# Generated by Django 5.2 on 2025-05-30 01:17 | |||
import django.db.models.deletion | |||
from django.conf import settings | |||
from django.db import migrations, models | |||
class Migration(migrations.Migration): | |||
initial = True | |||
dependencies = [ | |||
("Community", "0001_initial"), | |||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |||
] | |||
operations = [ | |||
migrations.AddField( | |||
model_name="comment", | |||
name="user", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="favorite", | |||
name="user", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="like", | |||
name="user", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="post", | |||
name="user", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="like", | |||
name="post", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to="Community.post" | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="favorite", | |||
name="post", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to="Community.post" | |||
), | |||
), | |||
migrations.AddField( | |||
model_name="comment", | |||
name="post", | |||
field=models.ForeignKey( | |||
on_delete=django.db.models.deletion.CASCADE, to="Community.post" | |||
), | |||
), | |||
] |
@ -0,0 +1,36 @@ | |||
from django.db import models | |||
from django.contrib.auth.models import User | |||
from django.conf import settings # 使用 Django 的配置抽象层 | |||
# 帖子模型 | |||
class Post(models.Model): | |||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) | |||
content = models.TextField(verbose_name="内容") | |||
image = models.ImageField(upload_to='post_images/', blank=True, null=True) | |||
video = models.FileField(upload_to='post_videos/', blank=True, null=True) | |||
like_count = models.PositiveIntegerField(default=0) # 👍 新增点赞字段 | |||
comment_count = models.PositiveIntegerField(default=0) # 👍 新增评论字段 | |||
favorite_count = models.PositiveIntegerField(default=0) # 👍 新增点赞字段 | |||
created_at = models.DateTimeField(auto_now_add=True) | |||
def __str__(self): | |||
return f"{self.user.username} 的帖子" | |||
# 互动模型(点赞、评论、收藏) | |||
class Like(models.Model): | |||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) | |||
post = models.ForeignKey(Post, on_delete=models.CASCADE) | |||
created_at = models.DateTimeField(auto_now_add=True) | |||
class Comment(models.Model): | |||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) | |||
post = models.ForeignKey(Post, on_delete=models.CASCADE) | |||
content = models.TextField() | |||
created_at = models.DateTimeField(auto_now_add=True) | |||
class Favorite(models.Model): | |||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) | |||
post = models.ForeignKey(Post, on_delete=models.CASCADE) | |||
created_at = models.DateTimeField(auto_now_add=True) |
@ -0,0 +1,3 @@ | |||
from django.test import TestCase | |||
# Create your tests here. |
@ -0,0 +1,15 @@ | |||
from django.urls import re_path as url | |||
from . import views | |||
from django.urls import path | |||
from django.conf.urls.static import static | |||
from django.conf import settings | |||
urlpatterns = [ | |||
path ('', views.post_list, name='community'), # 首页就是帖子列表 | |||
path('create_post/', views.create_post, name='create_post'), # 专用于发布逻辑 | |||
path ('post_list/', views.post_list, name='post_list'), # 浏览已发布帖子 | |||
path('like_post/<int:post_id>/', views.like_post, name='like_post'), # 点赞帖子 | |||
path('comment_post/<int:post_id>/', views.comment_post, name='comment_post'), # 评论帖子 | |||
path('favorite_post/<int:post_id>/', views.favorite_post, name='favorite_post'), # 收藏帖子 | |||
path('toggle_follow/<int:user_id>/', views.toggle_follow, name='toggle_follow'), # 关注 | |||
] |
@ -0,0 +1,134 @@ | |||
from django.shortcuts import render, redirect | |||
from .models import Post, Like, Comment, Favorite | |||
from MyPage.models import Follow | |||
from users.models import CustomUser | |||
from django.http import JsonResponse | |||
from django.contrib.auth.decorators import login_required | |||
from django.views.decorators.csrf import csrf_exempt | |||
def index(request): | |||
posts = Post.objects.all().order_by('-created_at') | |||
return render(request, 'Community.html', {'posts': posts}) | |||
@login_required(login_url='login') | |||
@csrf_exempt | |||
def create_post(request): | |||
if request.method == 'POST': | |||
content = request.POST.get('content', '').strip() | |||
image = request.FILES.get('image') | |||
video = request.FILES.get('video') | |||
if content or image or video: | |||
try: | |||
post = Post.objects.create( | |||
user=request.user, | |||
content=content, | |||
image=image, | |||
video=video | |||
) | |||
print("✅ 帖子成功写入数据库!ID:", post.id) | |||
except Exception as e: | |||
print("❌ 帖子写入失败:", e) | |||
else: | |||
print("⚠️ 无内容、图片或视频,跳过写入。") | |||
return redirect('community') | |||
# GET 请求展示帖子列表 | |||
posts = Post.objects.all().order_by('-created_at') | |||
return render(request, 'Community.html', {'posts': posts}) | |||
# 浏览已发布帖子 | |||
def post_list(request): | |||
posts = Post.objects.all().order_by('-created_at') | |||
return render(request, 'Community.html', {'posts': posts}) | |||
@login_required(login_url='login') | |||
@csrf_exempt | |||
def like_post(request, post_id): | |||
user = request.user | |||
try: | |||
post = Post.objects.get(id=post_id) | |||
# 检查是否已点赞 | |||
if Like.objects.filter(user=user, post=post).exists(): | |||
return JsonResponse({'success': False, 'message': '已点赞'}) | |||
# 没有则创建记录 | |||
Like.objects.create(user=user, post=post) | |||
post.like_count += 1 | |||
post.save() | |||
return JsonResponse({'success': True, 'likes': post.like_count}) | |||
except Post.DoesNotExist: | |||
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404) | |||
@login_required(login_url='login') | |||
@csrf_exempt | |||
def comment_post(request, post_id): | |||
if request.method == 'POST': | |||
content = request.POST.get('content', '').strip() | |||
if not content: | |||
return JsonResponse({'success': False, 'message': '评论不能为空'}) | |||
try: | |||
post = Post.objects.get(id=post_id) | |||
comment = Comment.objects.create(user=request.user, post=post, content=content) | |||
post.comment_count += 1 | |||
post.save() | |||
return JsonResponse({ | |||
'success': True, | |||
'username': comment.user.username, | |||
'content': comment.content, | |||
'created_at': comment.created_at.strftime('%Y-%m-%d %H:%M:%S'), | |||
'comment_count': post.comment_count | |||
}) | |||
except Post.DoesNotExist: | |||
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404) | |||
@login_required(login_url='login') | |||
@csrf_exempt | |||
def favorite_post(request, post_id): | |||
user = request.user | |||
try: | |||
post = Post.objects.get(id=post_id) | |||
# 检查是否已收藏 | |||
if Favorite.objects.filter(user=user, post=post).exists(): | |||
return JsonResponse({'success': False, 'message': '已收藏'}) | |||
# 没有则创建记录 | |||
Favorite.objects.create(user=user, post=post) | |||
post.favorite_count += 1 | |||
post.save() | |||
return JsonResponse({'success': True, 'favorites': post.favorite_count}) | |||
except Post.DoesNotExist: | |||
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404) | |||
@login_required(login_url='login') | |||
@csrf_exempt | |||
def toggle_follow(request, user_id): | |||
follower = request.user | |||
try: | |||
followed = CustomUser.objects.get(id=user_id) | |||
if follower == followed: | |||
return JsonResponse({'success': False, 'message': '不能关注自己'}) | |||
existing = Follow.objects.filter(follower=follower, followed=followed) | |||
if existing.exists(): | |||
existing.delete() | |||
return JsonResponse({'success': True, 'following': False, 'message': '已取消关注'}) | |||
else: | |||
Follow.objects.create(follower=follower, followed=followed) | |||
return JsonResponse({'success': True, 'following': True, 'message': '关注成功'}) | |||
except CustomUser.DoesNotExist: | |||
return JsonResponse({'success': False, 'message': '用户不存在'}) | |||
def post_list(request): | |||
posts = Post.objects.all().order_by('-created_at') | |||
user = request.user | |||
for post in posts: | |||
post.is_followed = False | |||
if user.is_authenticated and post.user != user: | |||
post.is_followed = Follow.objects.filter(follower=user, followed=post.user).exists() | |||
return render(request, 'Community.html', {'posts': posts}) |