#11670: Model fields named 'year', 'month', 'gt', 'lt' etc. get mistaken for 
lookup
types in lookups across relations
-------------------------------------+-------------------------------------
     Reporter:  andy@…               |                    Owner:
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  SVN
  (models, ORM)                      |               Resolution:
     Severity:  Normal               |             Triage Stage:  Accepted
     Keywords:                       |      Needs documentation:  0
    Has patch:  1                    |  Patch needs improvement:  1
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------
Changes (by akaariai):

 * cc: akaariai (added)


Comment:

 I have an idea, but maybe it is not workable. So, my first idea is to get
 the patch in as is, and revisit this issue later on.

 The maybe-unworkable idea is that the code for traveling the lookups
 translates to this logic (at least I think it does):
 {{{
 while lookup_leads_to_field:
     fields.append(found_field)
     if found_field is related_field:
         related_field = found_field.related_field
     else:
         goto marker1

 if lookups_left:
     if not allow_explicit_fk:
         raise FieldError
 marker1:
 ...
 }}}

 Now, if you get a lookup like `rel_field__non_existing_field` you are
 going to raise `FieldError`. But if you instead do
 `nonrel_field__non_existing_field` you are going to say that nonrel_field
 was found and non_existing_field part wasn't looked. This is because
 nonrel_field will "goto marker1" (via NotRelatedField exception) and skip
 the if lookups_left part.

 So, the only idea I have is to return the rel_field in the
 `rel_field__non_existing_field` lookup case. So, something like this:
 {{{
 # pseudoish...
 for counter, field_name in enumerate(parts):
     try:
         if field_name == 'pk':
             field_name = opts.pk.name
         field_info = opts.get_field_by_name(field_name)
         fields += (field_info,)
         if (counter + 1) < num_parts:
             # If we haven't reached the end of the list of
             # lookups yet, then let's attempt to continue
             # traversing relations.
             related_model = get_model_from_relation(field_info[0])
             opts = related_model._meta
     except FieldDoesNotExist, NotRelatedField:
         break
 if fields:
     # We found at least one field, lets return that
     last_field = fields[-1]
 else:
     # The lookup was totally bogus - it didn't resolve any field from
     # the base model
     raise FieldError
 return parts, fields, last_field
 }}}

 The caller is then responsible to raising `FieldError` if that is the
 appropriate action, doing the explicit_fk logic and checking for existing
 aggregates, etc. I haven't tried this at all, so it is possible this idea
 is bogus, or will make the caller's job more complicate than it needs to
 be.

 As said before: getting the patch in as is could be the thing to do.
 Polish it later on when we know how custom lookups are going to be
 handled. I have a tendency to over-complicate things, and I have a feeling
 I am in over-complicating mode right now... :)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/11670#comment:23>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

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

Reply via email to