Django:m2m关系创建两行而不是一行

Django:m2m关系创建两行而不是一行,django,many-to-many,django-orm,Django,Many To Many,Django Orm,我以这种方式扩展了UserModel: # users/models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # add additional fields in here credit = models.IntegerField(default=200) follow = mod

我以这种方式扩展了UserModel:

# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # add additional fields in here
    credit = models.IntegerField(default=200)
    follow = models.ManyToManyField('self', related_name='follow')
    def __str__(self):
        return self.username
但我一直在思考如何添加/删除跟随者。我创建了一个具有以下内容的视图:

@login_required
def follow(request, user_id):
    user = get_object_or_404(CustomUser, pk=user_id)
    if CustomUser.objects.filter(follow=user.pk).exists():
        request.user.follow.remove(user)
    else:
        request.user.follow.add(user)
    return redirect('profil', user_id)
问题: 假设request.user.pk为1,user_id为2

对于else中的add部分,我希望数据库中有一行from_customuser_id=1和to_customuser_id=2,但它会创建两行:

按预期,from_customuser_id=1和from_customuser_id=2的一个

一个from_customuser_id=2,from_customuser_id=1,我不需要

对于if中的remove部分,我希望它只删除行

from_customuser_id=1和from_customuser_id=2 但它删除了这两条线

我读了这篇文章,但没有找到解决这个问题的方法

问题: 我应该如何更新我的代码,以使add方法仅插入一行from_customuser_id=1、from_customuser_id=2,以及remove方法仅删除此行(假设当前用户的id为1)

不确定是否相关,但为了完整起见,这是my URL.py的相关部分:

path('follow/<int:user_id>', views.follow, name='follow'),
path('unfollow/<int:user_id>', views.follow, name='unfollow'),
这就是我在模板中对它们的称呼:

{% if follow %}
    <a href="{% url 'follow' user_profil.id %}">
        Unfollow {{ user_profil.username }}
    </a>
{% else %}
    <a href="{% url 'unfollow' user_profil.id %}">
        Follow {{ user_profil.username }}
    </a>
{% endif %}

当你有一个ManyToManyField时,它实际上在两个对象之间创建了一种关系。这也允许您进行反向查找

例如:

class Person(models.Model):
    name = model.CharField(max_length=100)

class Pet(models.Model):
    owners = models.ManyToMany(Person, related_name="pets")
    name = model.CharField(max_length=100)

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
kitty_kat = Pet.objects.create(name="Kitty Kat")
kitty_kat.owners.set([bob, john])
class Person(models.Model):
    name = model.CharField(max_length=100)
    followers = models.ManyToManyField('self', related_name='follow') 

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
john.followers.add(bob)

bob.follow.all()       # I get john... notice I use follow and not followers
john.followers.all()   # I get bob
根据这些模型,一只宠物可以由多人拥有,一个人可以养多只宠物。所以如果我这样做了

bob.pets.all()          # I get kitty kat
kitty_kay.owners.all()  # I get bob & john
当这个关系应该在同一个模型上时,您最终会创建两个关系。一个是正常的,一个是相反的

例如:

class Person(models.Model):
    name = model.CharField(max_length=100)

class Pet(models.Model):
    owners = models.ManyToMany(Person, related_name="pets")
    name = model.CharField(max_length=100)

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
kitty_kat = Pet.objects.create(name="Kitty Kat")
kitty_kat.owners.set([bob, john])
class Person(models.Model):
    name = model.CharField(max_length=100)
    followers = models.ManyToManyField('self', related_name='follow') 

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
john.followers.add(bob)

bob.follow.all()       # I get john... notice I use follow and not followers
john.followers.all()   # I get bob
为了避免这种情况,可以将symmetric=False传递给字段,并创建一行

followers = models.ManyToManyField('self', related_name='+', symmetrical=False)
将相关的_名称设置为以+开头的任何名称也将防止在本例中不需要的反向查找