有没有方法可以检查相关对象是否已经被提取?

2024-04-19 21:10:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望能够通过使用select_relatedprefetch_related来检查是否已经获取了相关的对象,以便能够相应地序列化数据。下面是一个例子:

class Address(models.Model):
    street = models.CharField(max_length=100)
    zip = models.CharField(max_length=10)

class Person(models.Model):
    name = models.CharField(max_length=20)
    address = models.ForeignKey(Address)

def serialize_address(address):
    return {
        "id": address.id,
        "street": address.street,
        "zip": address.zip
    }

def serialize_person(person):
    result = {
        "id": person.id,
        "name": person.name
    }
    if is_fetched(person.address):
        result["address"] = serialize_address(person.address)
    else:
        result["address"] = None

######

person_a = Person.objects.select_related("address").get(id=1)
person_b = Person.objects.get(id=2)

serialize_person(person_a) #should be object with id, name and address
serialize_person(person_b) #should be object with only id and name

在这个例子中,函数is_fetched就是我要找的。我想确定person对象是否已经有一个resolves地址,并且只有当它有时,它也应该被序列化。但如果没有,就不应该执行进一步的数据库查询。在

那么,在Django有没有实现这一点的方法呢?在


Tags: nameidstreetaddressmodelsresultzipselect
2条回答

如果已经获取了address关系,那么Person对象将有一个填充属性,名为_address_cache;您可以检查它。在

def is_fetched(obj, relation_name):
    cache_name = '_{}_cache'.format(relation_name)
    return getattr(obj, cache_name, False)

请注意,您需要使用对象和关系的名称来调用它:

^{pr2}$

因为执行person.address会立即触发获取。在

Editreverse或多对多关系只能由prefetch_related来获取,它填充了一个属性_prefetched_objects_cache,这是一个列表的dict,其中key是相关模型的名称。例如,如果你这样做:

addresses = Address.objects.prefetch_related('person_set')

那么addresses中的每个项目都将有一个_prefetched_objects_cachedict,其中包含一个"person'键。在

注意,这两个属性都是单下划线属性,这意味着它们是私有API的一部分;您可以自由使用它们,但Django也可以在将来的版本中自由地更改它们。在

由于Django 2.0您可以通过以下方法轻松检查所有获取的关系:

obj._state.fields_cache

^{}负责存储缓存的关系。在

^{pr2}$

相关问题 更多 >