Using GenericRelation lookups keyword arguments

6 views
Skip to first unread message

Litnimax

unread,
Nov 28, 2007, 8:58:02 PM11/28/07
to Django developers
Hello dear Django developers!

Can GenericRelation be used for the following lookup example?
Here subscription is .GenericRelation field name (see model
definitions below).

user_numbers =
LocalNumber.objects.filter(subscription__account=user_account)

I bet it WORKED! But today I noticed this code no longer return any
results only empty list.
I svn update daily and missed the moment it stopped to work.
I did some digging with svn log and svn diff in contenttypes but did
not find anything.

Test models are below:

class LocalNumber(models.Model):
number = models.CharField(_('number'), max_length=10, unique=True)
subscription = generic.GenericRelation(Subscription)


class Subscription(models.Model):
"""
Universal model for all subscriptions.
"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField(db_index=True)
account = models.ForeignKey(VoipAccount,
verbose_name=_("account"))
currency = models.ForeignKey(Currency, verbose_name=_("currency"))
period = models.IntegerField(_("period"), choices=PERIOD_CHOICES)
setup = models.DecimalField(
_("setup fee"), max_digits=10, decimal_places=2)
rate = models.DecimalField(
_("period rate"), max_digits=10, decimal_places=2)
create_date = models.DateTimeField(_("created on"), db_index=True)
paidtill_date = models.DateField(_("paid till"), db_index=True)
is_enabled = models.BooleanField(_("is enabled"), db_index=True)
content_object = generic.GenericForeignKey()

Litnimax

unread,
Nov 29, 2007, 5:31:59 AM11/29/07
to Django developers
I did some more investigations and seems I have found a bug probably
related to http://groups.google.com/group/django-developers/browse_thread/thread/53c9d7d877c318bd.
This is 100% bug.

The example below uses same models as in previous post.

print
LocalNumber.objects.filter(subscription__account=self)._get_sql_clause()

And here is the result:

(['`provider_localnumber`.`id`', '`provider_localnumber`.`pool_id`',
'`provider_localnumber`.`sub_pool_id`',
'`provider_localnumber`.`number`'], ' FROM `provider_localnumber` LEFT
OUTER JOIN `billing_subscription` AS
`m2m_provider_localnumber__subscription` ON
`provider_localnumber`.`id` =
`m2m_provider_localnumber__subscription`.`object_id` INNER JOIN
`billing_subscription` AS `provider_localnumber__subscription` ON
`m2m_provider_localnumber__subscription`.`object_id` =
`provider_localnumber__subscription`.`id` WHERE
(`provider_localnumber__subscription`.`account_id` = %s)', [20865L])

Please note the inner join
m2m_provider_localnumber__subscription`.`object_id` =
`provider_localnumber__subscription`.`id` - IT MUST BE object_id not
id!!!

For example, if we run this SQL we get no result:

mysql> select `provider_localnumber`.`id`,
`provider_localnumber`.`pool_id`,
`provider_localnumber`.`sub_pool_id`, `provider_localnumber`.`number`
FROM `provider_localnumber` LEFT OUTER JOIN `billing_subscription` AS
`m2m_provider_localnumber__subscription` ON
`provider_localnumber`.`id` =
`m2m_provider_localnumber__subscription`.`object_id` INNER JOIN
`billing_subscription` AS `provider_localnumber__subscription` ON
`m2m_provider_localnumber__subscription`.`object_id` =
`provider_localnumber__subscription`.`id` WHERE
(`provider_localnumber__subscription`.`account_id` = 20865);
Empty set (0.00 sec)

BUT IF WE CHANGE `provider_localnumber__subscription`.`id` to
`provider_localnumber__subscription`.`object_id` WE DO GET CORRECT
RESULT:

mysql> select `provider_localnumber`.`id`,
`provider_localnumber`.`pool_id`,
`provider_localnumber`.`sub_pool_id`, `provider_localnumber`.`number`
FROM `provider_localnumber` LEFT OUTER JOIN `billing_subscription` AS
`m2m_provider_localnumber__subscription` ON
`provider_localnumber`.`id` =
`m2m_provider_localnumber__subscription`.`object_id` INNER JOIN
`billing_subscription` AS `provider_localnumber__subscription` ON
`m2m_provider_localnumber__subscription`.`object_id` =
`provider_localnumber__subscription`.`object_id` WHERE
(`provider_localnumber__subscription`.`account_id` = 20865);
+-------+---------+-------------+--------+
| id | pool_id | sub_pool_id | number |
+-------+---------+-------------+--------+
| 46317 | 13 | 1 | 1000 |
| 46337 | 13 | 2 | 1020 |
+-------+---------+-------------+--------+
2 rows in set (0.00 sec)

Litnimax

unread,
Nov 29, 2007, 5:34:01 AM11/29/07
to Django developers
Main question is why do we have 2 JOINS instead of one?
And 2-nd inner join is apparently broken :-(

Regards,
Max.

Litnimax

unread,
Nov 29, 2007, 6:23:26 AM11/29/07
to Django developers
May be I was not clear may be I do not understand something or maybe I
am not understood?
Anyway here is the patch:

svn diff generic.py
Index: generic.py
===================================================================
--- generic.py (revision 6723)
+++ generic.py (working copy)
@@ -118,7 +118,7 @@
return self.object_id_field_name

def m2m_reverse_name(self):
- return self.object_id_field_name
+ return self.rel.to._meta.pk.name

def contribute_to_class(self, cls, name):
super(GenericRelation, self).contribute_to_class(cls, name)


I did not see in documentation any examples on how to use generic
relation for lookups so may be nobody is using it? :-)

SHALL I CREATE A TICKET!?

Litnimax

unread,
Nov 29, 2007, 7:53:54 AM11/29/07
to Django developers
Ticket created - http://code.djangoproject.com/ticket/6051
Regards,
Max.
Reply all
Reply to author
Forward
0 new messages