简体   繁体   English

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

[英]Perform lookup and update within a single Django query

I have two models: MetaModel and RelatedModel . 我有两个模型: MetaModelRelatedModel I want to include the result of a RelatedModel lookup within a MetaModel query, and I'd like to do this within a single DB call. 我想在MetaModel查询中包括一个RelatedModel查找的结果,我想在一个数据库调用中做到这一点。

I've tried to define a 'subquery' QuerySet for use in the main query, but that hasn't worked - it's still making two queries to complete the operation. 我试图定义一个“子查询” QuerySet以便在主查询中使用,但这没有用-它仍在进行两个查询以完成操作。

Note: I can't use a traditional ForeignKey relationship because the profile_id field is not unique. 注意:我不能使用传统的ForeignKey关系,因为profile_id字段不是唯一的。 Uniqueness is a combination of profile_id and channel . 唯一性是profile_idchannel的组合。 This is an aggregation table and profile_id is not guaranteed to be unique across multiple third-party channels. 这是一个聚合表,不能保证profile_id在多个第三方渠道之间是唯一的。

Any suggestions? 有什么建议么?

Models: 楷模:

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

Dummy data 虚拟数据

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)

Query: 查询:

# 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."}
)

Regarding your note on uniqueness, you can use unique_together option in Django as described here in the documentation . 关于唯一性的注释,您可以按照文档中的说明在Django中使用unique_together选项。

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

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

Then you can change your query accordingly and should solve your problem. 然后,您可以相应地更改查询,并应解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM