基于一对一关系从预先存在的过滤查询集中排除查询集
Exclude a QuerySet from a pre-existing filtered QuerySet based on a One-to-One relationship
我有一个包含三个模型的 Django 应用程序:
class Strategy(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
...
class Version(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
strategy = models.ForeignKey(Strategy, on_delete=models.CASCADE)
...
class Tool(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
version = models.OneToOneField(Version, on_delete=models.CASCADE)
...
在 Tool 模型对应的 ToolForm 上,我为 'version' 字段过滤了 QuerySet,以便用户只看到他们提交的策略版本:
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['version'].queryset = Version.objects.filter(strategy__user=user.id)
我现在想进一步过滤这个 QuerySet 以排除已经有工具的版本。版本与工具的关系是一对一的,我只希望用户看到仍然需要提交工具的版本。我尝试了多种方法,但我不断回到以下版本:
Version.objects.filter(strategy__user=user.id).exclude(Tool.objects.filter(version__strategy__user=user.id).values('version_id'))
Version.objects.filter(strategy__user=user.id).exclude(Tool.objects.filter(version__strategy__user=user.id).values_list('version_id'))
两个“排除”查询 return 工具条目的一对一字段 'version_id'。我得到的回复分别是:
'dict' object has no attribute 'split'
'tuple' object has no attribute 'split'
我错过了什么?如何从我的 ToolForm 'version' 字段中排除已经建立一对一关系的版本?
这里不需要排除。您可以简单地使用 tool__isnull=True
:
Version.objects.filter(strategy__user=user.id, tool__isnull=True)
由于 Version 和 Tool 实例之间的 OneToOne 关系,Version 有一个名为 tool
的字段(所有小写模型名称,除非您定义 related_name
)。对于没有工具的版本实例,该字段将为空。因此 isnull=True
将检查没有任何工具的 Version 实例。
我有一个包含三个模型的 Django 应用程序:
class Strategy(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
...
class Version(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
strategy = models.ForeignKey(Strategy, on_delete=models.CASCADE)
...
class Tool(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
version = models.OneToOneField(Version, on_delete=models.CASCADE)
...
在 Tool 模型对应的 ToolForm 上,我为 'version' 字段过滤了 QuerySet,以便用户只看到他们提交的策略版本:
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['version'].queryset = Version.objects.filter(strategy__user=user.id)
我现在想进一步过滤这个 QuerySet 以排除已经有工具的版本。版本与工具的关系是一对一的,我只希望用户看到仍然需要提交工具的版本。我尝试了多种方法,但我不断回到以下版本:
Version.objects.filter(strategy__user=user.id).exclude(Tool.objects.filter(version__strategy__user=user.id).values('version_id'))
Version.objects.filter(strategy__user=user.id).exclude(Tool.objects.filter(version__strategy__user=user.id).values_list('version_id'))
两个“排除”查询 return 工具条目的一对一字段 'version_id'。我得到的回复分别是:
'dict' object has no attribute 'split'
'tuple' object has no attribute 'split'
我错过了什么?如何从我的 ToolForm 'version' 字段中排除已经建立一对一关系的版本?
这里不需要排除。您可以简单地使用 tool__isnull=True
:
Version.objects.filter(strategy__user=user.id, tool__isnull=True)
由于 Version 和 Tool 实例之间的 OneToOne 关系,Version 有一个名为 tool
的字段(所有小写模型名称,除非您定义 related_name
)。对于没有工具的版本实例,该字段将为空。因此 isnull=True
将检查没有任何工具的 Version 实例。