当某些行为该相关对象返回空值时,如何使用select_related()?

时间:2019-04-29 17:10:54

标签: python django django-models

我想从成员身份请求)中获取两个相关的对象,但是我正在使用的查询是成员身份请求可能为空,而django不允许我这样做。 查询:

member = Member.objects.get(id=12345)
Group.objects.annotate(membership=FilteredRelation('members', condition=Q(members__member=member))) \
    .annotate(request=FilteredRelation('requests', condition=(requests__member=member))) \
    .filter(Q(membership__isnull=False) | Q(request__isnull=False)) \
    .select_related('membership', 'request')

与模型

class GroupMembership(models.Model):
    group = models.ForeignKey('group.Group', related_name='members', on_delete=models.CASCADE)
    member = models.ForeignKey(
        'group.Member',
        related_name='group_membership',
        on_delete=models.CASCADE,
    )

class GroupMembershipRequest(models.Model):
    group = models.ForeignKey('group.Group', related_name='requests',  on_delete=models.CASCADE)
    member = models.ForeignKey(
        'group.Member',
        related_name='group_membership_request',
        on_delete=models.CASCADE,
    )

但是我遇到以下错误:

Traceback (most recent call last):
  ...
  File "/Users/Project/venv/lib/python3.6/site-packages/django/db/models/query.py", line 1186, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/Users/Project/venv/lib/python3.6/site-packages/django/db/models/query.py", line 66, in __iter__
    rel_populator.populate(row, obj)
  File "/Users/Project/venv/lib/python3.6/site-packages/django/db/models/query.py", line 1830, in populate
    self.local_setter(from_obj, obj)
  File "/Users/Project/venv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 869, in local_setter
    f.remote_field.set_cached_value(from_obj, obj)
  File "/Users/Project/venv/lib/python3.6/site-packages/django/db/models/fields/mixins.py", line 23, in set_cached_value
    instance._state.fields_cache[self.get_cache_name()] = value
AttributeError: 'NoneType' object has no attribute '_state'

可能是由于查询的性质引起的(某些成员身份请求可以为空)。

还有一种方法可以通过单个查询来实现,即获取成员身份请求,即使它们为 Null 也是如此?< / p>

1 个答案:

答案 0 :(得分:0)

gm = GroupMembership.objects.filter(member=member,).values_list('group_id', flat=True)
gmr = GroupMembershipRequest.objects.filter(member=member,).values_list('group_id', flat=True)

g_ids = gm+gmr

Groups.objects.filter(id__in=g_ids,)

或者您可以尝试类似的

gm = GroupMembership.objects.filter(member=member, group_id=OuterRef('pk'), )
gmr = GroupMembershipRequest.objects.filter(member=member,group_id=OuterRef('pk'), )

Groups.objects.annotate(is_member=Exists(gm), has_requested=Exists(gmr),)
     .filter(Q(is_member=True)|Q(has_requested=True),)