django 左连接与 where 子句子表达式
django left join with where clause subexpression
我目前正在尝试找到一种方法来使用我认为应该可行的 Django (v1.10) ORM,但我正在努力了解如何应用记录的方法来解决我的问题。
编辑: 所以这里是 sql,我已经将它们整合到 return 我想要从 dbshell
,现在使用 postgresql 数据库,在我意识到我原来的 sqlite3 支持 sql 查询不正确之后:
select
voting_bill.*,vv.vote
from
voting_bill
left join
(select
voting_votes.vote,voting_votes.bill_id
from
voting_bill
left join
voting_votes
on
voting_bill.id=voting_votes.bill_id
where
voting_votes.voter_id = (select id from auth_user where username='richard' or username is Null)
)
as
vv
on
voting_bill.id=vv.bill_id;
这是我的投票应用 'models.py':
from django.db import models
from django.contrib.auth.models import User
class Bill(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
result = models.BooleanField()
status = models.BooleanField(default=False)
def __str__(self):
return self.name
class Votes(models.Model):
vote = models.NullBooleanField()
bill = models.ForeignKey(Bill, related_name='bill',
on_delete=models.CASCADE,)
voter = models.ForeignKey(User, on_delete=models.CASCADE,)
def __str__(self):
return '{0} {1}'.format(self.bill, self.voter)
我可以看到我的 sql 像我预期的那样工作,投票附加到最后,如果用户还没有投票,则为 null。
我正在努力使查询集采用这种格式,以便我可以在模板中对其进行迭代以生成 table,如果结果为 null,我可以改为提供 link将用户带到另一个视图。
我读过 select_related 和 prefetch_related,但正如我所说,我正在努力弄清楚如何将其转化为如何在 SQL 中做到这一点.
希望我正确理解了您的问题。试试这个:
votes = Votes.objects.filter(voter__username='django').select_related('bill')
你可以用这个。但我认为在这种情况下你不需要 select_related
。
bills_for_user = Bill.objects.filter(votes__voter__username='django').select_related('votes').distinct()
现在您可以迭代 bills_for_user
for bill in bills_for_user:
bill_name = bill.name
bill_description = bill.description
bill_result = bill.result
bill_status = bill.status
# and there are several variants what you can with votes
bill_votes = bill.votes_set.all() # will return you all votes for this bill
bill_first_vote1 = bill.votes_set.first() # will return first element in this query or None if its empty
bill_first_vote2 = bill.votes_set.all()[0] # will return first element in this query or Error if its empty
bill_last_vote = bill.votes_set.last()[0] # will return last element in this query or None if its empty
# you can also filter it for example by voting
bill_positive_votes = bill.votes_set.filter(vote=True) # will return you all votes for this bill with 'vote' = True
bill_negative_votes = bill.votes_set.filter(vote=False) # will return you all votes for this bill with 'vote' = False
bill_neutral_votes = bill.votes_set.filter(vote=None) # will return you all votes for this bill with 'vote' = None
我目前正在尝试找到一种方法来使用我认为应该可行的 Django (v1.10) ORM,但我正在努力了解如何应用记录的方法来解决我的问题。
编辑: 所以这里是 sql,我已经将它们整合到 return 我想要从 dbshell
,现在使用 postgresql 数据库,在我意识到我原来的 sqlite3 支持 sql 查询不正确之后:
select
voting_bill.*,vv.vote
from
voting_bill
left join
(select
voting_votes.vote,voting_votes.bill_id
from
voting_bill
left join
voting_votes
on
voting_bill.id=voting_votes.bill_id
where
voting_votes.voter_id = (select id from auth_user where username='richard' or username is Null)
)
as
vv
on
voting_bill.id=vv.bill_id;
这是我的投票应用 'models.py':
from django.db import models
from django.contrib.auth.models import User
class Bill(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
result = models.BooleanField()
status = models.BooleanField(default=False)
def __str__(self):
return self.name
class Votes(models.Model):
vote = models.NullBooleanField()
bill = models.ForeignKey(Bill, related_name='bill',
on_delete=models.CASCADE,)
voter = models.ForeignKey(User, on_delete=models.CASCADE,)
def __str__(self):
return '{0} {1}'.format(self.bill, self.voter)
我可以看到我的 sql 像我预期的那样工作,投票附加到最后,如果用户还没有投票,则为 null。
我正在努力使查询集采用这种格式,以便我可以在模板中对其进行迭代以生成 table,如果结果为 null,我可以改为提供 link将用户带到另一个视图。
我读过 select_related 和 prefetch_related,但正如我所说,我正在努力弄清楚如何将其转化为如何在 SQL 中做到这一点.
希望我正确理解了您的问题。试试这个:
votes = Votes.objects.filter(voter__username='django').select_related('bill')
你可以用这个。但我认为在这种情况下你不需要 select_related
。
bills_for_user = Bill.objects.filter(votes__voter__username='django').select_related('votes').distinct()
现在您可以迭代 bills_for_user
for bill in bills_for_user:
bill_name = bill.name
bill_description = bill.description
bill_result = bill.result
bill_status = bill.status
# and there are several variants what you can with votes
bill_votes = bill.votes_set.all() # will return you all votes for this bill
bill_first_vote1 = bill.votes_set.first() # will return first element in this query or None if its empty
bill_first_vote2 = bill.votes_set.all()[0] # will return first element in this query or Error if its empty
bill_last_vote = bill.votes_set.last()[0] # will return last element in this query or None if its empty
# you can also filter it for example by voting
bill_positive_votes = bill.votes_set.filter(vote=True) # will return you all votes for this bill with 'vote' = True
bill_negative_votes = bill.votes_set.filter(vote=False) # will return you all votes for this bill with 'vote' = False
bill_neutral_votes = bill.votes_set.filter(vote=None) # will return you all votes for this bill with 'vote' = None