python - 当某些行为该相关对象返回空值时,如何使用 select_related()?
问题描述
我想从组(成员资格和请求)中获取两个相关对象,但是对于我正在使用的查询,成员资格或请求可能为空,并且 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?
解决方案
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),)
推荐阅读
- javascript - js从本地上传图片
- uproot - 在 upROOT 中的 ROOT 功能?
- apache-spark - Spark 数据集写入 2 个不同的目录
- ios - MPMusicPlayerController 无法播放 Apple Music 歌曲
- python - 如何在 python 中导入字符串并对其进行分析和重构?
- asp.net - 如何在 ASP.NET 中设置需要身份验证的文件下载?
- python - 功能未实现:'lib' -> 'my/path/to/venv/lib64'
- vuejs2 - Wordpress Rest API:返回 100 多个结果
- python-requests - Python3 错误与 pyowm import OWM 产生 RequestsDependencyWarning:
- java - 尝试在 VSCode 中创建新的 Maven 项目时出现“错误:在您的环境中找不到 JAVA_HOME”