Как редактировать поле 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()
Вернуться на верх