Django Queryset - комплексный параметр отношения как переменная? - PullRequest
0 голосов
/ 20 января 2012

У меня есть географический объект, который используется в поисках близости. Этот объект связан с другими объектами различными путями.

Примеры:

  blog.geo_object
  user.profile.geo_object
  group.event.geo_object

Сейчас я делаю поиск в ограничивающей рамке, которая выглядит следующим образом:

radius_queryset = base_queryset.filter(
    user__profile__geo__lat__gte = bounding_box.lat_min,
    user__profile__geo__lat__lte = bounding_box.lat_max,
    user__profile__geo__lon__gte = bounding_box.lon_min,
    user__profile__geo__lon__lte = bounding_box.lon_max,

и затем на других объектах:

radius_queryset = base_queryset.filter(
    blog__geo__lat__gte = bounding_box.lat_min,
    blog__geo__lat__lte = bounding_box.lat_max,
    blog__geo__lon__gte = bounding_box.lon_min,
    blog__geo__lon__lte = bounding_box.lon_max,
)

Это следует общему формату:

radius_queryset = base_queryset.filter(
    [lookup_path]__geo__lat__gte = bounding_box.lat_min,
    [lookup_path]__geo__lat__lte = bounding_box.lat_max,
    [lookup_path]__geo__lon__gte = bounding_box.lon_min,
    [lookup_path]__geo__lon__lte = bounding_box.lon_max,
)
# where lookup_path = "blog"  or "user__profile" in the two above examples

Я пишу достаточно этих (еще 3, еще больше), чтобы захотеть обобщить запросы - инкапсуляция является хорошим другом для удобства сопровождения и союзником в борьбе с опечатками.

Итак, на мой вопрос: если не считать exec и eval (которые выглядят просто уродливо), есть ли способ получить имя параметра фильтра для подстановки в переменную? Я что-то упустил здесь?

Ответы [ 2 ]

4 голосов
/ 20 января 2012

**kwargs ваш ответ!

def generate_qs(lookup_path, bounding_box):
    return base_queryset.filter(**{
        lookup_path + '__geo__lat__gte' : bounding_box.lat_min,
        lookup_path + '__geo__lat__lte' : bounding_box.lat_max,
        lookup_path + '__geo__lon__gte' : bounding_box.lon_min,
        lookup_path + '__geo__lon__lte' : bounding_box.lon_max,
    })

radius_queryset = generate_qs('blog', bounding_box)
0 голосов
/ 20 января 2012

Я думаю, что вы можете использовать синтаксис Python **kwargs, чтобы избавиться от этой неприятности во вспомогательной функции. Что-то вроде:

def helper(lookup_path, bounding_box):
        return dict([ ("%s__geo__%s" % (lookup_path, lkup_left, ),
                       getattr(bounding_box, lkup_right), )
                     for lkup_left, lkup_right in
                     (("lat__gte", "lat_min", ),
                      ("lat__lte", "lat_max", ),
                      ("lon__gte", "lon_min", ),
                      ("lon__lte", "lon_max", ), 
                     ) ])

qs = base_queryset.filter(**helper(lookup_path, bounding_box))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...