python – 复杂的Django查询
|
我的大杂烩应用程序的查询超出了我对Django的ORM如何工作的了解.
这是我当前(不正确)的尝试: queryset = Mentor.objects.filter(
shift__session = session,jobs_desired = job
).exclude(
shift__session = session,shift__jobs__time = job.time
)
如果您想阅读它们,我的模型如下. 初始filter()工作正常.我的问题是将exclude()链接到最后. exclude()似乎排除了Mentors: >符合指定条件的关联Shift 我只想过滤出与其相关联的Shift的导师符合标准. 有任何想法吗? class DojoSession(models.Model):
term = models.ForeignKey(DojoTerm,help_text = "Dojo Term")
date = models.DateField(
blank = False,help_text = "Date during which the session will take place."
)
start = models.TimeField(
blank = False,help_text = "Start Time"
)
end = models.TimeField(
blank = False,help_text = "End Time"
)
rooms = models.ManyToManyField(
Room,blank = True,help_text = "The rooms in which this session will be running."
)
class Shift(models.Model):
mentor = models.ForeignKey(
'mentors.Mentor',blank = False,help_text = 'The mentor unergoing this shift.'
)
session = models.ForeignKey(
DojoSession,help_text = 'The session during which this shift takes place.',)
role = models.ForeignKey(
'mentors.Role',help_text = "The role that the mentor will be undertaking during this shift.",)
room = models.ForeignKey(
Room,null = True,help_text = "The room,if any,that the mentor will be undertaking the shift in."
)
jobs = models.ManyToManyField(
'jobs.Job',)
start = models.TimeField(
blank = False,help_text = "End Time"
)
class Job(models.Model):
BEFORE = 'B'
DURING = 'D'
AFTER = 'A'
TIME_CHOICES = (
(BEFORE,'Before session'),(DURING,'During session'),(AFTER,'After session'),)
name = models.CharField(
max_length = 50,help_text = "The job's name."
)
description = models.TextField(
max_length = 1024,help_text = "A description of the job."
)
location = models.CharField(
max_length = 50,help_text = "The job's location."
)
time = models.CharField(
max_length = 1,choices = TIME_CHOICES,help_text = "The time during a session at which this job can be carried out."
)
class Mentor(models.Model):
MALE_SMALL = "MS"
MALE_MEDIUM = "MM"
MALE_LARGE = "ML"
MALE_EXTRA_LARGE = "MXL"
FEMALE_EXTRA_SMALL = "FXS"
FEMALE_SMALL = "FS"
FEMALE_MEDIUM = "FM"
FEMALE_LARGE = "FL"
FEMALE_EXTRA_LARGE = "FXL"
SHIRT_SIZE_CHOICES = (
('Male',(
(MALE_SMALL,"Male S"),(MALE_MEDIUM,"Male M"),(MALE_LARGE,"Male L"),(MALE_EXTRA_LARGE,"Male XL")
)),('Female',(
(FEMALE_EXTRA_SMALL,"Female XS"),(FEMALE_SMALL,"Female S"),(FEMALE_MEDIUM,"Female M"),(FEMALE_LARGE,"Female L"),(FEMALE_EXTRA_LARGE,"Female XL")
))
)
ASSOCIATE = 'A'
STAFF = 'S'
NEITHER = 'N'
CURTIN_STATUS_CHOICES = (
(ASSOCIATE,'Associate'),(STAFF,'Staff'),(NEITHER,'Neither/not sure')
)
NOTHING = 'NO'
SOMETHING = 'SO'
EVERYTHING = 'EV'
KNOWLEDGE_CHOICES = (
(NOTHING,'I know nothing but am keen to learn!'),(SOMETHING,'I know some basics'),(EVERYTHING,'I know a great deal')
)
uni = models.CharField(
max_length = 50,help_text = "University of study"
)
uni_study = models.CharField(
max_length = 256,help_text = "If you're attending university,what are you studying?"
)
work = models.CharField(
max_length = 256,help_text = "If you workwhat do you do?"
)
shirt_size = models.CharField(
max_length = 3,choices = SHIRT_SIZE_CHOICES,help_text = "T-shirt size (for uniform)"
)
needs_shirt = models.BooleanField(
default = True,help_text = "Does the mentor need to have a shirt provisioned for them?"
)
wwcc = models.CharField(
max_length = 10,verbose_name = "WWCC card number",help_text = "WWCC card number (if WWCC card holder)"
)
wwcc_receipt = models.CharField(
max_length = 15,verbose_name = "WWCC receipt number",help_text = "WWCC receipt number (if WWCC is processing)"
)
curtin_status = models.CharField(
max_length = 1,verbose_name = "Current Curtin HR status",choices = CURTIN_STATUS_CHOICES,default = NEITHER,help_text = "When possible,we recommend that all CoderDojo mentors are either Curtin University Associates or Staff members."
)
curtin_id = models.CharField(
max_length = 10,verbose_name = "Curtin Staff/Associate ID",help_text = "Your Curtin Staff/Associate ID (if applicable)"
)
coding_experience = models.CharField(
max_length = 2,default = NOTHING,choices = KNOWLEDGE_CHOICES,help_text = "How much programming experience do you have?"
)
children_experience = models.CharField(
max_length = 2,help_text = "How much experience do you have with children?"
)
roles_desired = models.ManyToManyField(Role)
jobs_desired = models.ManyToManyField('jobs.Job')
shift_availabilities = models.ManyToManyField(
'planner.DojoSession',help_text = "When are you available?"
)
user = models.OneToOneField(settings.AUTH_USER_MODEL,unique = True
)
解决方法
首先,我们来解释一下这里发生了什么.当你写:
set.exclude( A=arg1,B=arg2 ) 这转换为以下查询: SELECT [...] WHERE NOT (A=arg1 AND B=arg2) 在boolean algebra中,?(A∧B)(不是[A和B])实际上是(?A∨?B)(不是[A] OR而不是[B]). SELECT [...] WHERE NOT(A=arg1) OR NOT(B=arg2) 编写具有多个参数的excludefilter时,请记住这一点. 因此,如果在您的查询中,您想要排除检查BOTH标准的元素(如果您愿意,那么标准的交集),最简单和最好的方法是链排除过滤器: set.exclude(A=arg1).exclude(B=arg2) 查询集操作是惰性的,大致意味着您的排除过滤器将同时进行评估.因此,两个过滤器不会是“工作的两倍”. 过滤器将转换为: SELECT [...] WHERE NOT(A=arg1) AND NOT(B=arg2) 这正是你想要的! 编写查询有时很难,但请记住: >排除多个args转换为:not(A)OR not(B)OR not(C)…… 现在,这是您的新查询: queryset = Mentor.objects.filter(
shift__session = session,jobs_desired = job
).exclude(
shift__session = session
).exclude(
shift__jobs__time = job.time
)
如果我们“扁平化”您的要求,您需要: >属于会话的记录:filter(shift__session = session) 生成的SQL将是: SELECT [...] WHERE shift__session = session AND [...] AND NOT(shift__session = session) 但是A∧?A(A AND NOT [A])是空集.所以问题在于查询的语义. 从你的帖子我读到:
您使用的过滤器已经保证shift__session = session,因此您不应将其放在排除过滤器中. 根据我的猜测(但告诉我,如果我错了),你想要的是: queryset = Mentor.objects.filter(
shift__session = session,jobs_desired = job
).exclude(
shift__jobs__time = job.time
)
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
