Как редактировать поле ManyToManyField в методе сохранения модели save()?
У меня есть метод, в котором есть обязательное поле для автора и необязательное поле для соавторов. Иногда человек, который создает пост, непреднамеренно или по незнанию выбирает свой профиль в качестве соавтора. Я хотел бы удалить фактического автора из соавторов, и я думаю, что лучший способ сделать это - переопределить метод save() модели. Вот что у меня есть на данный момент, но, похоже, это не работает.
models.py
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
User = get_user_model()
class Post(models.Model):
PUBLICATION_STATUS_CHOICES = [
("PUBLIC", _("public")),
("PRIVATE", _("private")),
("DRAFT", _("draft")),
]
title = models.CharField(max_length=100, verbose_name=_("post title"))
summary = models.CharField(max_length=250, verbose_name=_("post summary"))
content = models.TextField(verbose_name=_("post content"))
is_markdown = models.BooleanField(default=True, verbose_name=_("Markdown"), help_text=_("Is this a post written in Markdown format?"))
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts", verbose_name=_("author of the post"))
coauthors = models.ManyToManyField(User, blank=True, related_name="colab_posts", verbose_name=_("colaborators / co-authors"))
date_created = models.DateTimeField(default=now, verbose_name=_("date of creation"))
date_updated = models.DateTimeField(default=now, verbose_name=_("last update"))
status = models.CharField(max_length=10, choices=PUBLICATION_STATUS_CHOICES, default=PUBLICATION_STATUS_CHOICES[0][0], verbose_name=_("post status"))
slug = models.SlugField(unique=True, verbose_name=_("slug"))
class Meta:
ordering = ["-date_created"]
verbose_name = _("post")
verbose_name_plural = _("posts")
def __str__(self):
return f"{self.title} ← {self.author} ({self.date_created.strftime('%Y-%m-%d %H:%M:%S')})"
def get_absolute_url(self):
return reverse("blog:post_details", args=[self.slug])
def save(self, *args, **kwargs):
if self.author in self.coauthors.all():
self.coauthors.remove(self.author)
super(Post, self).save(*args, **kwargs)
IMO post_save signal будет лучшим способом сделать это. Сохраните модель как обычно, а затем в сигнале post_save удалите автора из соавторов.
пример кода:
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Post)
def validate_post_authors(sender, instance, **kwargs):
post_author = instance.author
instance.coauthors.remove(post_author)
instance.save()