保存 CustomUser 模型时 Django ManyToMany 被覆盖
Django ManyToMany overwritten when saving CustomUser model
概览
我正在创建一个友谊模型来跟踪相互关注的用户。我创建了一个扩展 AbstractUser 的 CustomUser 模型和一个用于 create/track 交互的单独的 UserRelationship 模型。我还有一个 signal.py 文件,用于处理两个模型(CustomUser 和 UserRelationship)之间的实际保存。
问题
创建友谊时(PK=1 的用户跟随 PK=2 的用户),PK=1 的用户的 Following ManyToMany 字段会正确更新,但是如果 PK=1 的用户更新他们的个人资料,则所有 ManyToMany字段被擦除。
模型自定义用户
class CustomUser(AbstractUser):
# Model manager
objects = CustomUserManager()
# Local
email = models.CharField(max_length=80, blank=True)
biography = models.CharField(max_length=100, blank=True)
photo = models.ImageField(
upload_to="users/%Y/%m/%d/",
blank=True,
default="static/images/default_profile_pic.png",
)
hidden = models.BooleanField(default=False)
# ForeignKey
following = models.ManyToManyField(
"CustomUser", related_name="followings", blank=True
)
follower = models.ManyToManyField(
"CustomUser", related_name="followers", blank=True
)
blocked = models.ManyToManyField("CustomUser", related_name="blocks", blank=True)
blocked_user_visible = models.ManyToManyField(
"CustomUser", related_name="block_user_visible", blank=True
)
hidden_request = models.ManyToManyField(
"CustomUser", related_name="hidden_requests", blank=True
)
def get_relationships(self):
return self.relationship.all()
def get_following(self):
return self.followings.all()
def get_relationships_number(self):
return self.relationship.all().count()
def __str__(self):
return self.username
def get_absolute_url(self):
return f"/users/{self.username}"
用户关系模型
class UserRelationship(models.Model):
STATUS_CHOICES = (
("sent", "sent"),
("accepted", "accepted"),
("deleted", "deleted"),
("blocked", "blocked"),
)
# Local
status = models.CharField(max_length=8, choices=STATUS_CHOICES, blank=True)
updated = models.DateTimeField(auto_now=True)
date_added = models.DateTimeField(auto_now_add=True)
# ForeignKey
# You have received a request from
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="from_user"
)
# You have sent a request to
following = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
related_name="to_user",
)
def __str__(self):
return f"{self.user} sent a friend request to {self.following}, status == {self.status}"
示例:JSON 创建 UserRelationship 后
{
"url": "http://localhost:8000/api/v1/users/1/",
"pk": 1,
"username": "test",
"first_name": "removed forWhosebug",
"last_name": "removed forWhosebug",
"email": "removed forWhosebug",
"hidden": false,
"following": [
44
],
"follower": [],
"blocked": [],
"hidden_request": [],
"photo": "https://azure.blob.core.windows.net/media/users/2020/06/28/test-36b9cdd1da48477dbb738b2f63ffca5f.jpg",
"biography": "Friday Aug 7"
}
示例:JSON更新用户测试的传记字段后(以下不再显示用户的pk“44”)
{
"url": "http://localhost:8000/api/v1/users/1/",
"pk": 1,
"username": "test",
"first_name": "removed forWhosebug",
"last_name": "removed forWhosebug",
"email": "removed forWhosebug",
"hidden": false,
"following": [],
"follower": [],
"blocked": [],
"hidden_request": [],
"photo": "https://azure.blob.core.windows.net/media/users/2020/06/28/test-36b9cdd1da48477dbb738b2f63ffca5f.jpg",
"biography": "This was updated"
}
Signals.py
@receiver(post_save, sender=UserRelationship)
def add_friend(sender, instance, created, **kwargs):
"""Signal function that responds to status of either
accepted, sent, blocked"""
sender_ = instance.user
receiver_ = instance.following
if instance.status == "accepted":
# If receiver's pk is already in sender's following M2M
if sender_.following.filter(pk=receiver_.pk).exists():
# Print (turn to HttpResponse)
print(f"You're already friends with {receiver_.username}")
# If sender's status is hidden
if receiver_.hidden:
instance.status = "sent"
# Add sender to receiver's hidden_request M2M (for notification & approvals)
receiver_.hidden_request.add(sender_.pk)
receiver_.save()
else:
# Else sender_ now follows the receiver
sender_.following.add(receiver_.pk)
# Receiver_ also now follows the sender
# Optional (Facebook style friendship, remove for twitter style friendship)
# receiver_.follower.add(sender_.pk)
# Save sender_
sender_.save()
# Save receiver_
receiver_.save()
编辑
我忘了说,我正在使用管理门户创建 UserRelationship,我还使用 Django-Rest-Framework 为 PK=1 的用户更新传记字段。我还尝试删除 signals.py 中 add_friend 函数的 else 块中的保存部分,只留下添加部分,结果是一样的。
我通过将 PUT 更改为 PATCH 解决了这个问题
概览
我正在创建一个友谊模型来跟踪相互关注的用户。我创建了一个扩展 AbstractUser 的 CustomUser 模型和一个用于 create/track 交互的单独的 UserRelationship 模型。我还有一个 signal.py 文件,用于处理两个模型(CustomUser 和 UserRelationship)之间的实际保存。
问题
创建友谊时(PK=1 的用户跟随 PK=2 的用户),PK=1 的用户的 Following ManyToMany 字段会正确更新,但是如果 PK=1 的用户更新他们的个人资料,则所有 ManyToMany字段被擦除。
模型自定义用户
class CustomUser(AbstractUser):
# Model manager
objects = CustomUserManager()
# Local
email = models.CharField(max_length=80, blank=True)
biography = models.CharField(max_length=100, blank=True)
photo = models.ImageField(
upload_to="users/%Y/%m/%d/",
blank=True,
default="static/images/default_profile_pic.png",
)
hidden = models.BooleanField(default=False)
# ForeignKey
following = models.ManyToManyField(
"CustomUser", related_name="followings", blank=True
)
follower = models.ManyToManyField(
"CustomUser", related_name="followers", blank=True
)
blocked = models.ManyToManyField("CustomUser", related_name="blocks", blank=True)
blocked_user_visible = models.ManyToManyField(
"CustomUser", related_name="block_user_visible", blank=True
)
hidden_request = models.ManyToManyField(
"CustomUser", related_name="hidden_requests", blank=True
)
def get_relationships(self):
return self.relationship.all()
def get_following(self):
return self.followings.all()
def get_relationships_number(self):
return self.relationship.all().count()
def __str__(self):
return self.username
def get_absolute_url(self):
return f"/users/{self.username}"
用户关系模型
class UserRelationship(models.Model):
STATUS_CHOICES = (
("sent", "sent"),
("accepted", "accepted"),
("deleted", "deleted"),
("blocked", "blocked"),
)
# Local
status = models.CharField(max_length=8, choices=STATUS_CHOICES, blank=True)
updated = models.DateTimeField(auto_now=True)
date_added = models.DateTimeField(auto_now_add=True)
# ForeignKey
# You have received a request from
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="from_user"
)
# You have sent a request to
following = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
related_name="to_user",
)
def __str__(self):
return f"{self.user} sent a friend request to {self.following}, status == {self.status}"
示例:JSON 创建 UserRelationship 后
{
"url": "http://localhost:8000/api/v1/users/1/",
"pk": 1,
"username": "test",
"first_name": "removed forWhosebug",
"last_name": "removed forWhosebug",
"email": "removed forWhosebug",
"hidden": false,
"following": [
44
],
"follower": [],
"blocked": [],
"hidden_request": [],
"photo": "https://azure.blob.core.windows.net/media/users/2020/06/28/test-36b9cdd1da48477dbb738b2f63ffca5f.jpg",
"biography": "Friday Aug 7"
}
示例:JSON更新用户测试的传记字段后(以下不再显示用户的pk“44”)
{
"url": "http://localhost:8000/api/v1/users/1/",
"pk": 1,
"username": "test",
"first_name": "removed forWhosebug",
"last_name": "removed forWhosebug",
"email": "removed forWhosebug",
"hidden": false,
"following": [],
"follower": [],
"blocked": [],
"hidden_request": [],
"photo": "https://azure.blob.core.windows.net/media/users/2020/06/28/test-36b9cdd1da48477dbb738b2f63ffca5f.jpg",
"biography": "This was updated"
}
Signals.py
@receiver(post_save, sender=UserRelationship)
def add_friend(sender, instance, created, **kwargs):
"""Signal function that responds to status of either
accepted, sent, blocked"""
sender_ = instance.user
receiver_ = instance.following
if instance.status == "accepted":
# If receiver's pk is already in sender's following M2M
if sender_.following.filter(pk=receiver_.pk).exists():
# Print (turn to HttpResponse)
print(f"You're already friends with {receiver_.username}")
# If sender's status is hidden
if receiver_.hidden:
instance.status = "sent"
# Add sender to receiver's hidden_request M2M (for notification & approvals)
receiver_.hidden_request.add(sender_.pk)
receiver_.save()
else:
# Else sender_ now follows the receiver
sender_.following.add(receiver_.pk)
# Receiver_ also now follows the sender
# Optional (Facebook style friendship, remove for twitter style friendship)
# receiver_.follower.add(sender_.pk)
# Save sender_
sender_.save()
# Save receiver_
receiver_.save()
编辑 我忘了说,我正在使用管理门户创建 UserRelationship,我还使用 Django-Rest-Framework 为 PK=1 的用户更新传记字段。我还尝试删除 signals.py 中 add_friend 函数的 else 块中的保存部分,只留下添加部分,结果是一样的。
我通过将 PUT 更改为 PATCH 解决了这个问题