Saturday, October 15, 2011

Using .filter() on a constant expression

I have some gnarly AND/OR logic combining Q() objects but deep
within the logic, I need to do a comparison of two constants. In
an ideal world, the logic would look something like

def age(self, age):
... & Q(12=as_of.month) & ...

but that's invalid python.

I *can* break out this rats' nest of logic into individual
queries, evaluate the constant expression, conditionally OR the
logic into the tree, then reassemble all the parts. However,
that gets even uglier. Actual code is included below
("dob"="date of birth", "dod"="date of death"; the "as_of" is a
datetime.date instance; part of the complication is that the
month/day DOB/DOD can be absent and the year can be an
approximate range, e.g. born between 1943 and 1947; and the age
query can be for a single age or a range of ages, e.g. 47-52
years old) and I'm looking to make the magic happen at the two
places marked "MAGIC HAPPENS HERE".

I tried hacking it with

Q(dob_month=F(str(as_of.month))-11)

(since dob_month is known to be 1 at this point) but that gives me

FieldError: Cannot resolve keyword '6' into field. Choices
are: <named fields from my model>

when I run my tests. Trying without wrapping the number in str()
complains that my integer/month has no attribute .split() (which
obviously it doesn't).

Is there any way to include a constant comparison in a Q()?

Thanks,

-tim

######################################

alive_q = use_as_of & (
# dob1 >= y1
Q(dob_year_min__gt=alive_y1) | (
Q(dob_year_min=alive_y1) & (
Q(dob_month=None) |
Q(dob_month__gt=as_of.month) | (
Q(dob_month=as_of.month) & (
Q(dob_day=None) |
Q(dob_day__gte=as_of.day)
))
)) | (
Q(dob_month=1) &
Q("""MAGIC HAPPENS HERE checking if as_of.month=12""") & (
Q(dob_day=None) |
(Q(dob_day=1) & Q("""MAGIC HAPPENS HERE checking if
as_of.day=31"""))
))
) & (
# dob2 < y2
Q(dob_year_max__lt=alive_y2) | (
Q(dob_year_max=alive_y2) & (
Q(dob_month=None) |
Q(dob_month__lt=as_of.month) | (
Q(dob_month=as_of.month) & (
Q(dob_day=None) |
Q(dob_day__lt=as_of.day)
))
)) | (
Q(dob_year_max=alive_y2+1) & (
Q(dob_month=1) & (
Q(dob_day=None) |
Q(dob_day__lt=1)
))
))
dead_q = use_dod & (
# dob1 >= y1
Q(dob_year_min__gt=dead_y1) | (
Q(dob_year_min=dead_y1) & (
Q(dob_month=None) |
Q(dod_month=None) |
Q(dob_month__gt=F("dod_month")) | (
Q(dob_month=F("dod_month")) & (
Q(dob_day=None) |
Q(dod_day=None) |
Q(dob_day__gte=F("dod_day"))
)) | (
Q(dob_month=1, dod_month=12) & (
Q(dob_day=None) |
Q(dod_day=None) |
Q(dob_day=1, dod_day=31)
))
))
) & (
# dob2 < y2
Q(dob_year_max__lt=dead_y2) | (
Q(dob_year_max=dead_y2) & (
Q(dob_month=None) |
Q(dod_month=None) |
Q(dob_month__lt=F("dod_month")) | (
Q(dob_month=F("dod_month")) & (
Q(dob_day=None) |
Q(dod_day=None) |
Q(dob_day__lt=F("dod_day"))
))
))
)
master_q = (alive_q | dead_q)
return self.get_query_set().filter(master_q)

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home


Real Estate