Django 上的用户追随者模型。不能在指定中间模型的 ManyToManyField 上使用 add()。改用accounts.Contact的经理

Posted

技术标签:

【中文标题】Django 上的用户追随者模型。不能在指定中间模型的 ManyToManyField 上使用 add()。改用accounts.Contact的经理【英文标题】:User Follower model on Django. Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead 【发布时间】:2018-11-12 12:36:30 【问题描述】:

我是 Django 新手,请原谅任何代码或逻辑中的愚蠢错误,

简介: 我正在尝试在 Django 中创建用户关注者模型。用户可以在哪些地方关注和取消关注网站上的其他用户

错误:我已经为我的关注/取消关注创建了models 我还创建了views 我收到了这个错误

AttributeError at /accounts/admin/follow/
Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead. 

obj.followers.add(user) 在回溯中突出显示为错误的来源

以下是我的 models.py

from django.contrib.auth.models import User
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    city = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    def get_absolute_url(self):
        return reverse('accounts:profile', kwargs='username': self.user.username)

class Contact(models.Model):
    user_from = models.ForeignKey(User, related_name='suppporter')
    user_to = models.ForeignKey(User, related_name='leader')

    def __str__(self):
        return ' follows '.format(self.user_from, self.user_to)


User.add_to_class('following',
                  models.ManyToManyField('self', through=Contact, related_name='followers', symmetrical=False))

我认为models.py 可能不错。我认为错误在于我的观点。 下面是我的 view.py

class FollowToggle(LoginRequiredMixin, RedirectView):

    def get_redirect_url(self, *args, **kwargs):
        username = self.kwargs.get('username')
        print(username + " This is the user who will be followed") # This prints correct
        profile = get_object_or_404(Profile, user__username=username)
        print(profile) # This prints correct
        obj = get_object_or_404(User, username=username)
        print(obj) # This prints correct
        url_ = profile.get_absolute_url()
        print(url_) # This prints correct
        user = self.request.user
        print(user) # This prints correct
        if user.is_authenticated():
            if user in obj.followers.all(): # I know this is the source of the error.
                obj.followers.remove(user)
            else:
                obj.followers.add(user)
        return url_

下面是 Urls.py 以防万一

url(r'^(?P<username>[-\w]+)/follow/$', views.FollowToggle.as_view(), name='follow'),

【问题讨论】:

【参考方案1】:

您不能将addremove 方法用于通过第三模型定义的多对多关系。来自docs:

与普通的多对多字段不同,您不能使用 add()、create() 或 set() 来创建关系

您应该使用Contact 经理:

if user.is_authenticated():
    if user in obj.followers.all(): # I know this is the source of the error.
        Contact.objects.filter(user_to=obj, user_from=user).delete()
    else:
        Contact.objects.create(user_to=obj, user_from=user)

【讨论】:

【参考方案2】:

在 Django 2.2 中,您可以使用 addremoveset 方法 (Docs)

您也可以使用 add()、create() 或 set() 来创建关系,只要您为任何必填字段指定 through_defaults 即可

【讨论】:

以上是关于Django 上的用户追随者模型。不能在指定中间模型的 ManyToManyField 上使用 add()。改用accounts.Contact的经理的主要内容,如果未能解决你的问题,请参考以下文章

Django 模型:用户和关注者的数据库设计

关注Django中的twitter用户,你会怎么做?

django 无法在指定中间模型的 ManyToManyField 上设置值。改用管理器

Django - 如何构建适合的中间 m2m 模型? / 最佳实践

Python-Django模型迁移用户数据库模型的迁移(对其他数据库迁移同样适用)!!!

django模型系统--多对多,一对一以及跨表查询