Django用户订阅关系实现求助:基于默认User模型构建博主订阅功能
嘿,我来帮你搞定这个Django博客的用户订阅功能!核心需求是实现用户之间的订阅关系——普通用户能关注文章作者,一个用户可以follow多个作者,一个作者也能被多个用户关注。结合你现有的Post模型和默认User模型,这里有两种实用的实现方案,你可以根据需求选择:
实现Django博客用户订阅功能
方案一:创建独立的Subscription模型(推荐,扩展性强)
这种方式的优势是可以轻松添加订阅时间、是否开启通知等额外字段,后续功能扩展会更灵活。
1. 定义Subscription模型
在你的app的models.py中添加以下代码:
from django.db import models from django.contrib.auth.models import User class Subscription(models.Model): # 订阅者(主动关注他人的用户) follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name="following") # 被订阅者(被关注的作者) followed = models.ForeignKey(User, on_delete=models.CASCADE, related_name="followers") # 自动记录订阅时间 created_at = models.DateTimeField(auto_now_add=True) class Meta: # 强制一个用户不能重复订阅同一个作者 unique_together = ('follower', 'followed') verbose_name = "订阅" verbose_name_plural = "订阅列表" def __str__(self): return f"{self.follower.username} 订阅了 {self.followed.username}"
2. 执行数据库迁移
运行以下命令更新数据库结构:
python manage.py makemigrations python manage.py migrate
3. 实现订阅/取消订阅的视图
在views.py中添加视图函数(这里用函数视图举例,类视图逻辑类似):
from django.shortcuts import get_object_or_404, redirect from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from .models import Subscription @login_required def toggle_subscription(request, user_id): # 获取目标作者 author = get_object_or_404(User, id=user_id) # 防止用户订阅自己 if request.user == author: return redirect('post_list') # 替换成你的文章列表页URL名称 # 检查是否已订阅,存在则取消,不存在则创建 subscription, created = Subscription.objects.get_or_create( follower=request.user, followed=author ) if not created: subscription.delete() # 跳转回作者的文章页或之前的页面 return redirect('author_posts', author_id=author.id) # 替换成你的作者文章页URL名称
4. 添加URL路由
在urls.py中添加路由规则:
from django.urls import path from . import views urlpatterns = [ # 其他现有路由... path('subscribe/<int:user_id>/', views.toggle_subscription, name='toggle_subscription'), ]
5. 在模板中添加订阅按钮
在作者的文章页或用户信息页,插入订阅/取消订阅的按钮:
{% if user.is_authenticated and user != author %} {% if user in author.followers.all %} <a href="{% url 'toggle_subscription' author.id %}" class="btn btn-danger">取消订阅</a> {% else %} <a href="{% url 'toggle_subscription' author.id %}" class="btn btn-primary">订阅</a> {% endif %} {% endif %}
方案二:直接用User的ManyToMany关联(轻量版)
如果不需要额外字段,只是单纯实现订阅关系,可以通过User模型的ManyToMany字段简化实现。由于默认User模型无法直接修改,我们用OneToOne关联的Profile模型来扩展:
1. 定义UserProfile模型
from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') # 存储用户关注的作者列表 following = models.ManyToManyField(User, related_name='followed_by', blank=True) def __str__(self): return self.user.username
添加信号自动为新用户创建Profile(放在models.py末尾):
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
执行数据库迁移后,这个模型就生效了。
2. 简化版订阅/取消视图
@login_required def toggle_subscription(request, user_id): author = get_object_or_404(User, id=user_id) if request.user == author: return redirect('post_list') # 切换订阅状态 if author in request.user.profile.following.all(): request.user.profile.following.remove(author) else: request.user.profile.following.add(author) return redirect('author_posts', author_id=author.id)
模板中的按钮逻辑只需修改判断条件:
{% if user.is_authenticated and user != author %} {% if author in user.profile.following.all %} <a href="{% url 'toggle_subscription' author.id %}" class="btn btn-danger">取消订阅</a> {% else %} <a href="{% url 'toggle_subscription' author.id %}" class="btn btn-primary">订阅</a> {% endif %} {% endif %}
额外功能:展示订阅列表与粉丝列表
在用户个人页面可以添加以下代码,展示用户的关注列表和粉丝列表:
<h3>我关注的作者</h3> <ul> {% for user in request.user.following.all %} {# 方案一用这个 #} {% comment %} {% for user in request.user.profile.following.all %} {# 方案二用这个 #} {% endcomment %} <li><a href="{% url 'author_posts' user.id %}">{{ user.username }}</a></li> {% empty %} <li>还没有关注任何作者</li> {% endfor %} </ul> <h3>我的粉丝</h3> <ul> {% for user in request.user.followers.all %} {# 方案一用这个 #} {% comment %} {% for user in request.user.followed_by.all %} {# 方案二用这个 #} {% endcomment %} <li>{{ user.username }}</li> {% empty %} <li>还没有粉丝</li> {% endfor %} </ul>
内容的提问来源于stack exchange,提问作者Sasha
相关产品推荐
相关产品推荐

