#27149: Filtering with generic relation
-------------------------------------+-------------------------------------
Reporter: MikiSoft | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version:
(models, ORM) |
Severity: Normal | Resolution:
Keywords: QuerySet.extra | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by MikiSoft):
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Old description:
> The following function is used for filtering by generic relation (and
> also by one column in the model where it is) which isn't natively
> supported by Django.
>
> {{{
> def generic_rel_filter(model, target, column, id):
> return model.objects.extra(where=['''
> {app_label}_{model}.id in (select object_id
> from {app_label}_{target}
> where content_type_id = (select id from django_content_type where
> model = '{model}')
> and {column} =
> {id})'''.format(app_label=os.path.basename(os.path.dirname(__file__)),
> model=model.__name__.lower(), target=target, column=column, id=id)])
> }}}
>
> ''Example:'' If I have Event and Like model, and the second one has
> generic relation to the first one (i.e. it has `content_type`,
> `object_id` and `content_object` fields), then if I want to get all
> events which current user liked, I would just make this call in a view:
> `generic_rel_filter(Event, 'like', 'person', self.request.user.pk)`
>
> '''Note that this function isn't intended to be used with user specified
> parameters, otherwise it's prone to SQL injection attacks.'''
New description:
The following function is used for filtering by generic relation (and also
by one column in the model where it is) which isn't natively supported by
Django.
{{{
def generic_rel_filter(model, target, column, id):
return model.objects.extra(where=['''
{app_label}_{model}.id in (select object_id
from {app_label}_{target}
where content_type_id = (select id from django_content_type where
model = '{model}')
and {column} =
{id})'''.format(app_label=os.path.basename(os.path.dirname(__file__)),
model=model.__name__.lower(), target=target, column=column, id=id)])
}}}
''Example:'' If I have Event and Like model, and the second one has
generic relation to the first one (i.e. it has `content_type`, `object_id`
and `content_object` fields), then if I want to get all events which
current user liked, I would just make this call in a view:
`generic_rel_filter(Event, 'like', 'person', self.request.user.pk)`
'''Note that this function isn't intended to be used with user specified
parameters, otherwise it's prone to SQL injection attacks.'''
P.S. It can be done with ORM but then it would go with three queries,
which is much slower than the method above (which uses only one query to
do the same):
`Event.objects.filter(pk__in=Like.objects.filter(content_type=ContentType.objects.get(model='event'),
person=self.request.user).values_list('object_id', flat=True))`
--
--
Ticket URL: <https://code.djangoproject.com/ticket/27149#comment:1>
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 unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/066.dbdf1b6b87230efab31f4be26828ebed%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.