Django изменить поле для каждого объекта в ManyToManyField - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть две модели с отношением ManyToMany, например:

# 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')

Когда создается ContentBuild, я хочу, чтобы все Filesets, которые находятся в этом ContentBuild, имели в своем поле in_content_build значение True.

Я пытался добиться этого с помощью сигнала post_save, но я не знаю, как получить все связанные Filesets.

Моя попытка сигнала:

# 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

Как мне установить in_content_build на True для всех наборов файлов в созданном экземпляре ContentBuild?

Ответы [ 3 ]

1 голос
/ 30 апреля 2019

Вы не можете действительно делать то, что вы хотите в сигнале, потому что post_save будет отправлено до того, как установлено filesets. Вы должны обрабатывать это везде, где вы создаете экземпляр, а не пытаться сделать это в сигнале.

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)

Еще одна вещь, на которую следует обратить внимание, это то, что вы нарушаете нормализацию этим полем. Вы можете отфильтровать наборы файлов, связанные с ContentBuild с:

Fileset.objects.filter(
    content_filesets__isnull=False,
)
1 голос
/ 30 апреля 2019

Вы можете установить in_content_build на True по умолчанию

in_content_build = models.BooleanField(default=True)

ОБНОВЛЕНИЕ: Если я правильно вас понимаю, вы используете in_content_build для проверки, установлен ли FileSetпринадлежит одному из ContentBuilds.Если это так, вам не нужно это поле вообще.Вы можете просто использовать функцию, которая будет выполнять проверку

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')
0 голосов
/ 30 апреля 2019

Попробуйте:

content_build = ContentBuild.objects.get(content_build_uuid=instance.content_build_uuid)
content_build.filesets.all().update(in_content_build=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...