Django:m2m 关系创建两行而不是一行
Django : m2m relationship create two line instead of one
我以这种方式扩展了 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
但我不知道应该如何 add/remove 一个追随者。我创建了一个视图:
@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。
对于 add
部分(在 else
中),我希望数据库中有一个新行 from_customuser_id=1
和 to_customuser_id=2
但是,它创建了两行:
一个 from_customuser_id=1
和 from_customuser_id=2
符合预期
一个 from_customuser_id=2
和 from_customuser_id=1
我不需要。
对于 remove
部分(在 if
中),我希望它只删除行
from_customuser_id=1
和 from_customuser_id=2
但是它删除了这两行。
我阅读了 doc about django models relations 但没有找到解决此问题的方法。
问题:
我应该如何更新我的代码才能让 add
方法只插入一行,from_customuser_id=1
、from_customuser_id=2
和 remove
方法只删除这一行(假设当前用户的 ID 为 1)。
不确定它是否相关,但为了完整起见,这是我 urls.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])
根据这些模型,一只宠物可以被多人拥有,一个人可以拥有多只宠物。所以如果我这样做
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)
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
为了避免这种情况,您可以将 symmetrical=False
传递给该字段,然后将创建一行
followers = models.ManyToManyField('self', related_name='+', symmetrical=False)
将 related_name
设置为任何以 +
开头的内容也将阻止反向查找(在这种情况下不需要)
我以这种方式扩展了 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
但我不知道应该如何 add/remove 一个追随者。我创建了一个视图:
@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。
对于 add
部分(在 else
中),我希望数据库中有一个新行 from_customuser_id=1
和 to_customuser_id=2
但是,它创建了两行:
一个
from_customuser_id=1
和from_customuser_id=2
符合预期一个
from_customuser_id=2
和from_customuser_id=1
我不需要。
对于 remove
部分(在 if
中),我希望它只删除行
from_customuser_id=1
和from_customuser_id=2
但是它删除了这两行。
我阅读了 doc about django models relations 但没有找到解决此问题的方法。
问题:
我应该如何更新我的代码才能让 add
方法只插入一行,from_customuser_id=1
、from_customuser_id=2
和 remove
方法只删除这一行(假设当前用户的 ID 为 1)。
不确定它是否相关,但为了完整起见,这是我 urls.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])
根据这些模型,一只宠物可以被多人拥有,一个人可以拥有多只宠物。所以如果我这样做
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)
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
为了避免这种情况,您可以将 symmetrical=False
传递给该字段,然后将创建一行
followers = models.ManyToManyField('self', related_name='+', symmetrical=False)
将 related_name
设置为任何以 +
开头的内容也将阻止反向查找(在这种情况下不需要)