Как сделать LEFT OUTER JOIN без внешнего ключа с помощью django orm
У меня есть следующие модели:
class User(Model):
###
user fields
###
class CaseModel(Model):
id = # django build in id field
owner = models.ForeignKey('User')
###
other fields
###
class DraftMessageModel(Model):
entity_id = models.IntegerField(null=True, blank=True) # CaseModel.id is linked to this
###
other fields
###
Мне нужно построить queryset, который генерирует следующий SQL:
SELECT
C.id,
C.some_field,
D.another_field,
U.username,
< some extra fields >
FROM
CaseModel AS C
LEFT OUTER JOIN User AS U ON (C.owner_id = U.id)
LEFT OUTER JOIN DraftMessageModel AS D ON (C.id = D.entity_id)
WHERE
C.owner_id = 100
AND < some extra condition >
Я знаю, что это банальный вопрос, но я не смог справиться с ним queryset.extra
или queryset.annotate(draft_message=FilteredRelation())
.
Вот что я пробовал до сих пор:
- queryset.annotate
queryset = CaseModel.objects.select_related('owner').filter(owner_id=100)
queryset = queryset.annotate(
draft_message=FilteredRelation(
'draftmessagemodel',
condition=Q(draftmessagemodel__entity_id=F('id'))
)
)
# error: Cannot resolve keyword 'draftmessagemodel' into field. Choices are: <CaseModel's other fields>
- queryset.extra
queryset = CaseModel.objects.select_related('owner').filter(owner_id=100)
queryset = queryset.extra(
select={
'draftmessagemodel__id': 'draftmessagemodel.id',
'draftmessagemodel__text': 'draftmessagemodel.text',
},
tables=['draftmessagemodel'],
where=[
'casemodel.id = draftmessagemodel.entity_id'
]
)
генерирование нежелательного sql:
SELECT
"casemodel"."id",
"user"."username",
(draftmessagemodel.id) AS "draftmessagemodel__id",
(draftmessagemodel.text) AS "draftmessagemodel__text",
<some other fields>
FROM
"casemodel"
LEFT OUTER JOIN "user" ON (
"casemodel"."owner_id" = "user"."id"
), -- I didn't unserstand from where this comma come here
"draftmessagemodel"
WHERE
(
"casemodel"."owner_id" = 100
AND (
casemodel.id = draftmessagemodel.entity_id
)
)
Здравствуйте. Я пользователь Django из Кореи.
Я не знаю. что именно вы хотите (потому что вы предоставили только частичную информацию), но вы можете примерно действовать следующим образом.
a = DraftMessageModel.objects.get({filter})
b = User.objects.get({filter})
CaseModel.objects.only('id', 'username', 'draftmessagemodel_id').filter(owner_id=100, id=a.entity_id, owner_id=b.id).annotate(draftmessagemodel__text='draftmessagemodel__text')