在单个Django查询中执行查找和更新

时间:2017-11-16 11:58:05

标签: python django postgresql

我有两个模型:MetaModelRelatedModel。我想在RelatedModel查询中包含MetaModel查询的结果,并且我希望在单个数据库调用中执行此操作。

我试图定义一个'子查询' QuerySet用于主查询,但尚未生效 - 它仍在进行两次查询以完成操作。

注意:我无法使用传统的ForeignKey关系,因为profile_id字段不是唯一的。唯一性是profile_idchannel的组合。这是一个聚合表,profile_id不保证在多个第三方渠道中是唯一的。

有什么建议吗?

型号:

class Channel(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(
        max_length=25,
    )

class MetaModel(models.Model):
    profile_id = fields.IntegerField()
    channel = fields.ForeignKey(Channel))
    metadata = fields.TextField()

class RelatedModel(models.Model):
    related_id = fields.IntegerField()
    profile_id = fields.IntegerField()
    channel = fields.ForeignKey(Channel))

虚拟数据

channel = Channel("Web site A")
channel.save()

sample_meta = MetaModel(profile_id=1234, channel=channel)
sample_related = RelatedModel(profile_id=1234, related_id=5678, channel=channel)

查询:

# Create a queryset to filter down to the single record we need the `profile_id` for
# I've limited to the only field we need via a `values` operation 
related_qs = RelatedAccount.objects.filter(
    related_id=5678,
    channel=channel
).values_list("profile_id", flat=True)

# I'm doing an update_or_create as there is other data to store, not included for brevity
obj, created = MetaModel.objects.update_or_create(
    profile_id=related_qs.first(),  # <<< This var is the dynamic part of the query
    channel=channel,
    defaults={"metadata": "Metadata is added to a new or existing record."}
)

1 个答案:

答案 0 :(得分:0)

关于唯一性的说明,您可以使用Django中的unique_together选项,如documentation中所述。

class MetaModel(models.Model):
    profile_id = fields.ForeignKey(RelatedModel)
    channel = fields.ForeignKey(Channel)
    metadata = fields.TextField()

    class Meta:
        unique_together = ('profile_id', 'channel')

然后您可以相应地更改您的查询,并解决您的问题。