'Django add element in manytomany relationship inside the save method
I try to add the author field in viewed_by manytomany relationship when the model is saved but nothing is added and I don't know why. I also try to use signals with post_save but nothing it don't work. Please help me.
class Message(AbstractCreateUpdate):
class TypeMessage(models.TextChoices):
TEXT = "TEXT"
EVENT = "EVENT"
IDEA = "IDEA"
UPDATE = "UPDATE"
id = models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False)
showcase = models.ForeignKey("Showcase",
on_delete=models.CASCADE,
related_name="messages",
related_query_name="messages")
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="messages",
related_query_name="messages")
type_message = models.CharField(max_length=32,
choices=TypeMessage.choices)
viewed_by = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name="messages_visualize",
related_query_name="messages_visualize",
blank=True)
class Meta(AbstractCreateUpdate.Meta):
db_table = "message"
verbose_name = _("Message")
verbose_name_plural = _("Messages")
def save(self, *args, **kwargs):
message = super().save(*args,**kwargs)
if not self.viewed_by.filter(id=self.author.id).exists():
self.viewed_by.add(self.author)
return message
def __str__(self): return str(self.id)
Moreover, in another models with a custom manytomany relationship this script to save a fields in manytomany work.
class Project(AbstractFile,AbstractCreateUpdate):
__link_site_help_text = _("Link del sito di contatto del progetto")
__ended_at_help_text = _("Data di chiusura del progetto. Se null il progetto è aperto")
__num_swipe_help_text = _("Il numero di swipe fatti dal progetto")
__tags_help_text = _("I tags che identificano il progetto")
id = models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False)
creator = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name="projects_created",
related_query_name="projects_created")
name = models.CharField(_("name"),unique=True,max_length=64)
description = models.TextField(_("description"),max_length=516,null=True,blank=True)
image = models.ImageField(_("image"), blank=True, null=True,upload_to=image_path)
link_site = models.TextField(_("link site"), blank=True, null=True,
help_text=__link_site_help_text,
max_length=516)
ended_at = models.DateField(_("ended"),null=True, blank=True,
help_text=__ended_at_help_text)
num_swipe = models.PositiveBigIntegerField(_("number swipe"), default=0,
help_text=__num_swipe_help_text)
tags = models.ManyToManyField(ProjectTag,
related_name="projects",
related_query_name="projects",
help_text=__tags_help_text,
blank=True)
users = models.ManyToManyField(settings.AUTH_USER_MODEL,
through="UserProject",
through_fields=("project", "user"),
related_name="projects",
related_query_name="projects")
class Meta(AbstractCreateUpdate.Meta):
db_table = "project"
verbose_name = _("Project")
verbose_name_plural = _("Projects")
constraints = [
CheckConstraint(check=Q(ended_at__lte=Now()),name="check_ended_at"),
CheckConstraint(check=Q(updated_at__gte=F('created_at')),name="check_project_updated_at")
]
@property
def ended(self):
return self.ended_at.strftime('%d %B %Y')
def save(self,*args, **kwargs):
project = super().save(*args,**kwargs)
self.setup_creator()
return project
def setup_creator(self):
if not self.users.filter(id=self.creator.id).exists():
self.users.add(self.creator)
Solution 1:[1]
The many to many relations are saved in a separate table, with your primary key and the foreign keys to reference the related models (in this case the user and the message).
With self.viewed_by.filter(id=self.author.id).exists() you're filtering the value of these primary key. Probably in your database exists a relation with the same primary key that the user. You need filter by the "user_id" or similar property:
self.viewed_by.filter(user_id=self.author.id).exists()
But, since you use settings.AUTH_USER_MODEL, best filter from user through the related_name:
self.author.messages_visualize.filter(message=self).exists()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tonio |
