Reputation: 3387
I have two models with a ManyToMany
relationship like this:
# models.py
class Fileset(models.Model):
fileset_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
name = models.CharField(max_length=50)
in_content_build = models.BooleanField(default=False)
class ContentBuild(models.Model):
content_build_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
filesets = models.ManyToManyField(Fileset, related_name='content_filesets')
When a ContentBuild
is created I want all the Filesets
that are in this ContentBuild
to have their in_content_build
field set to True
.
I tried to achieve this by using a post_save
signal but I have no idea how to get all the related Filesets
.
My attempt at a signal:
# signals.py
@receiver(post_save, sender=ContentBuild)
def set_fileset_as_deployed(sender, instance, **kwargs):
try:
content_build = ContentBuild.objects.get(content_build_uuid=instance.content_build_uuid)
for fileset in content_build.filesets:
fileset.in_content_build = True
fileset.save()
except ContentBuild.DoesNotExist:
pass
How would I be able to set in_content_build
to True
for all Filesets in the created ContentBuild
instance?
Upvotes: 0
Views: 42
Reputation: 13731
You can't really do what you want in a signal because post_save
will be sent before the filesets
is set. You should handle this wherever you are creating the instance rather than trying to do it within a signal.
content_build = create_content_build() # Or whatever you're using.
content_build.file_sets.set([some_fileset_queryset])
# If you can do it here, then do:
some_fileset_queryset.update(in_content_build=True)
# Otherwise:
content_build.file_sets.all().update(in_content_build=True)
Another thing to point out is that you're breaking normalization with this field. You could filter down to filesets that are associated with a ContentBuild
with:
Fileset.objects.filter(
content_filesets__isnull=False,
)
Upvotes: 1
Reputation: 683
Try:
content_build = ContentBuild.objects.get(content_build_uuid=instance.content_build_uuid)
content_build.filesets.all().update(in_content_build=True)
Upvotes: 0
Reputation: 2279
You can set in_content_build
to be True
by default
in_content_build = models.BooleanField(default=True)
UPDATE : If I understand you correctly, you are using in_content_build
to check if a FileSet belongs to one of the ContentBuilds. If that's the case, you don't need that field at all. You can just use a function that will perform the check
class Fileset(models.Model):
fileset_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
name = models.CharField(max_length=50)
def is_in_content_build(self):
for cb in ContentBuild.objects.all():
for fs in cb.filesets.all():
if self.fileset_uuid == fs.fileset_uuid
return True
return False
class ContentBuild(models.Model):
content_build_uuid = models.UUIDField(primary_key=True,
default=uuid.uuid4, editable=False, db_index=True)
filesets = models.ManyToManyField(Fileset, related_name='content_filesets')
Upvotes: 1