Django ORM:反向关系从单个模型查询多个模型
Django ORM: Reverse relation query multiple model from single models
我在查询反向关系时遇到了麻烦,我学到了很多关于select_related
和prefetch_related
的知识,但我没有实现。
初看我的模特:
from django.db import models
import uuid
class Person(models.Model):
alias = models.UUIDField(primary_key=True,default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=20)
class Appointment(models.Model):
patient = models.ForeignKey(Person, related_name="patient_for_appointment", on_delete=models.CASCADE)
data = models.CharField(max_length=20)
class Sales(models.Model):
customer = models.ForeignKey(Person, related_name="customer_for_sales", on_delete=models.CASCADE)
amount = models.FloatField()
class Prescription(models.Model):
patient = models.ForeignKey(Person, related_name="Patient_for_prescription", on_delete=models.CASCADE)
details = models.CharField(max_length=100)
我正在尝试过滤 Person
模型以检查此人是否有任何 prescription
、sales
和 appointment
我想通过一次查询获得所有这些喜欢这个人。将用一个人alias
(主键)
过滤它
我可以用像
这样的单独查询来过滤它
patient_alias = '53fsdfsdf-fdsfds-df-fdf'
queryset = Appointment.objects.filter(
patient__alias=patient_alias
)
但我不想要这个,因为它有性能问题。我不希望使用单独的查询。
我只想查询 Person
模型来检查一个人是否有预约、处方或销售
喜欢Person.objects.filter(alias='a person alias)
谁能帮我实现这个目标?
非常感谢
我们可以 select 所有 Person
,除了那些没有 Appointment
,也没有 Sales
或 Prescription
的 [=18] =]
Person.objects.exclude(
patient_for_appointment=None,
customer_for_sales=None,
Patient_for_prescription=None
)
这将生成如下所示的查询:
SELECT person.alias, person.name
FROM person
WHERE NOT (
person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN prescription U1 ON U0.alias = U1.patient_id
WHERE U1.id IS NULL
)
AND person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN sales U1 ON U0.alias = U1.customer_id
WHERE U1.id IS NULL AND U0.alias = person.alias
)
AND person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN appointment U1
ON U0.alias = U1.patient_id
WHERE U1.id IS NULL AND U0.alias = person.alias
)
)
或者我们可以联合起来,比如:
Person.objects.filter(
patient_for_appointment__isnull=False
).union(
Person.objects.filter(customer_for_sales__isnull=False),
Person.objects.filter(Patient_for_prescription__isnull=False)
)
这将产生如下所示的查询:
(
SELECT person.alias, person.name
FROM person
INNER JOIN appointment ON person.alias = appointment.patient_id
WHERE appointment.id IS NOT NULL
) UNION (
SELECT person.alias, person.name FROM person
INNER JOIN sales ON person.alias = sales.customer_id
WHERE sales.id IS NOT NULL
) UNION (
SELECT person.alias, person.name
FROM person
INNER JOIN prescription ON person.alias = prescription.patient_id
WHERE prescription.id IS NOT NULL
)
我在查询反向关系时遇到了麻烦,我学到了很多关于select_related
和prefetch_related
的知识,但我没有实现。
初看我的模特:
from django.db import models
import uuid
class Person(models.Model):
alias = models.UUIDField(primary_key=True,default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=20)
class Appointment(models.Model):
patient = models.ForeignKey(Person, related_name="patient_for_appointment", on_delete=models.CASCADE)
data = models.CharField(max_length=20)
class Sales(models.Model):
customer = models.ForeignKey(Person, related_name="customer_for_sales", on_delete=models.CASCADE)
amount = models.FloatField()
class Prescription(models.Model):
patient = models.ForeignKey(Person, related_name="Patient_for_prescription", on_delete=models.CASCADE)
details = models.CharField(max_length=100)
我正在尝试过滤 Person
模型以检查此人是否有任何 prescription
、sales
和 appointment
我想通过一次查询获得所有这些喜欢这个人。将用一个人alias
(主键)
我可以用像
这样的单独查询来过滤它patient_alias = '53fsdfsdf-fdsfds-df-fdf'
queryset = Appointment.objects.filter(
patient__alias=patient_alias
)
但我不想要这个,因为它有性能问题。我不希望使用单独的查询。
我只想查询 Person
模型来检查一个人是否有预约、处方或销售
喜欢Person.objects.filter(alias='a person alias)
谁能帮我实现这个目标?
非常感谢
我们可以 select 所有 Person
,除了那些没有 Appointment
,也没有 Sales
或 Prescription
的 [=18] =]
Person.objects.exclude(
patient_for_appointment=None,
customer_for_sales=None,
Patient_for_prescription=None
)
这将生成如下所示的查询:
SELECT person.alias, person.name
FROM person
WHERE NOT (
person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN prescription U1 ON U0.alias = U1.patient_id
WHERE U1.id IS NULL
)
AND person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN sales U1 ON U0.alias = U1.customer_id
WHERE U1.id IS NULL AND U0.alias = person.alias
)
AND person.alias IN (
SELECT U0.alias
FROM person U0
LEFT OUTER JOIN appointment U1
ON U0.alias = U1.patient_id
WHERE U1.id IS NULL AND U0.alias = person.alias
)
)
或者我们可以联合起来,比如:
Person.objects.filter(
patient_for_appointment__isnull=False
).union(
Person.objects.filter(customer_for_sales__isnull=False),
Person.objects.filter(Patient_for_prescription__isnull=False)
)
这将产生如下所示的查询:
(
SELECT person.alias, person.name
FROM person
INNER JOIN appointment ON person.alias = appointment.patient_id
WHERE appointment.id IS NOT NULL
) UNION (
SELECT person.alias, person.name FROM person
INNER JOIN sales ON person.alias = sales.customer_id
WHERE sales.id IS NOT NULL
) UNION (
SELECT person.alias, person.name
FROM person
INNER JOIN prescription ON person.alias = prescription.patient_id
WHERE prescription.id IS NOT NULL
)