我有一个用于邻近搜索的地理对象。该对象通过各种路径键入不同的其他对象。
示例:
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(看起来很难看),有没有办法让过滤器参数名称变为sub-in变量?我在这里错过了一些简单的东西吗?
答案 0 :(得分:4)
**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)
答案 1 :(得分:0)
我认为你可以使用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))