Django用户关注系统报错:no such column: blog_follow.followed_by_id
Django关注/取消关注系统错误修复方案
问题概述
开发Django用户关注系统时,访问页面触发错误:django.db.utils.OperationalError: no such column: blog_follow.followed_by_id,删除迁移文件重新执行makemigrations和migrate后问题仍存在。
核心错误原因
- 模型设计逻辑错误:
User模型的followers字段错误关联了Follow模型,而非直接建立用户间的多对多关系,导致数据库表结构与代码逻辑不匹配。 - 迁移未正确同步:之前的错误模型生成的迁移文件未彻底清理,数据库表结构未更新到正确状态。
- 视图与模板的逻辑错误:视图中查询条件错误,模板中存在变量引用错误(如
i.user.id应为i.id)。
分步修复方案
1. 修正模型结构
修改models.py,正确建立用户间的关注关系,利用Django的ManyToManyField结合自定义中间表:
from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): # following表示当前用户关注的人,followers表示关注当前用户的人 following = models.ManyToManyField( "self", through='Follow', symmetrical=False, related_name='followers' ) class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) post = models.CharField(max_length=500, null=True, blank=True) timestamp = models.DateField(auto_now_add=True) like = models.ManyToManyField(User, blank=True, related_name="liked_posts") @property def number_of_likes(self): return self.like.all().count() def __str__(self) -> str: return self.post[:20] # 显示前20个字符避免过长 class Follow(models.Model): followed_me = models.ForeignKey(User, on_delete=models.CASCADE, related_name='follow_records') followed_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='following_records') created_at = models.DateTimeField(auto_now_add=True) # 记录关注时间 class Meta: unique_together = ('followed_me', 'followed_by') # 禁止重复关注同一用户 def __str__(self) -> str: return f"{self.followed_by.username} 关注了 {self.followed_me.username}"
2. 重置迁移与数据库
注意:此操作会清空数据库数据,建议先备份数据!
- 删除app目录下
migrations文件夹中除__init__.py外的所有文件 - 删除项目根目录的
db.sqlite3文件(如果使用其他数据库,需手动清空对应表) - 重新生成迁移文件:
python manage.py makemigrations - 同步数据库:
python manage.py migrate
3. 修正视图逻辑
修改views.py中的查询与操作逻辑:
from django.shortcuts import render, get_object_or_404, redirect from .models import User, Post, Follow def profile(request, username): my_account = get_object_or_404(User, username=username) my_post = Post.objects.filter(user=my_account).order_by("-timestamp") # 最新帖子在前 following = False if request.user.is_authenticated: # 检查当前用户是否关注了目标用户 following = my_account.followers.filter(id=request.user.id).exists() # 统计粉丝数与关注数 follower_count = my_account.followers.count() following_count = my_account.following.count() return render(request, "blog/profile.html", { "posts": my_post, "post_count": my_post.count(), "following": following, "follower_count": follower_count, "following_count": following_count, "my_account": my_account }) def follow_list(request): all_users = User.objects.all() return render(request, "blog/following.html", { "al_us": all_users }) def follow_or_unfollow_user(request, user_id): if not request.user.is_authenticated: return redirect('login') # 未登录用户跳转登录页面 followed_user = get_object_or_404(User, id=user_id) if followed_user == request.user: return redirect('profile', username=request.user.username) # 禁止关注自己 # 切换关注状态 follow_record, created = Follow.objects.get_or_create( followed_me=followed_user, followed_by=request.user ) if not created: follow_record.delete() return redirect('profile', username=followed_user.username)
4. 修正模板错误
profile.html
<div> 总帖子数 {{ post_count }} <span>总粉丝数 {{ follower_count }}</span> <span>关注数 {{ following_count }}</span> {% if user.is_authenticated and user != my_account %} {% if following %} <a href="{% url 'follow_or_unfollow' my_account.id %}">取消关注</a> {% else %} <a href="{% url 'follow_or_unfollow' my_account.id %}">关注</a> {% endif %} {% endif %} </div> {% for pst in posts %} <div class="post-outer-container"> <div class="post-container"> {{ pst.post }} <p>作者:{{ pst.user.username }} | 发布时间:{{ pst.timestamp }}</p> {% if user.id == pst.user.id %} <a href="{% url 'edit-post' pst.id %}" style="margin-left:15px ;">编辑</a> <a href="{% url 'delete' pst.id %}" style="margin-left:15px ;">删除</a> {% endif %} </div> </div> {% endfor %}
following.html
<h1>所有用户</h1> {% for user_obj in al_us %} {% if user.id != user_obj.id %} <div>{{ user_obj.username }}</div> {% if user_obj in user.following.all %} <a href="{% url 'follow_or_unfollow' user_obj.id %}">取消关注</a> {% else %} <a href="{% url 'follow_or_unfollow' user_obj.id %}">关注</a> {% endif %} {% endif %} {% endfor %}
5. 修正URL配置
确保urls.py中的路径正确:
from django.urls import path from . import views urlpatterns = [ path("profile/<str:username>", views.profile, name="profile"), path("follow/list", views.follow_list, name="follow_list"), path("follow_or_unfollow/<int:user_id>", views.follow_or_unfollow_user, name="follow_or_unfollow"), # 其他URL... ]
验证修复
- 创建测试用户
- 访问用户主页,尝试关注/取消关注操作
- 检查粉丝数、关注数是否正确更新
- 确认页面不再出现
no such column错误
内容的提问来源于stack exchange,提问作者Mert Altintas
相关产品推荐
相关产品推荐

