注意:由于与生产环境相关的限制,我目前正在使用Django-1.4并且无法升级到1.7。
我写了一个自定义字段JsonListField
。基本上它是一个TextField {J}在从DB读取时的值,json.loads
在写入时它的值。它允许我直接操作简单对象的python列表。
现在,有时候,我想查询这个字段。例如:
json.dumps
我想要的是匹配我在列表中的确切值。
我能做到:
MyModelClass.objects.query(listfield__contains="term").all()
但是对于API的用户,我希望这样做的侵入性较小:使用MyModelClass.objects.query(listfield__regexp=r'"term"[,\]]').all()
查找并将其即时更改为regexp。
我想我可以使用自定义字段的contains
方法来生成正则表达式。但我也希望此功能告诉数据库与get_db_prep_lookup
而不是REGEXP
匹配。
我有一种预感,我可以创建一个实现LIKE
的对象,但我不确定我是否在正确的轨道上,并且不确定这是否可行。
答案 0 :(得分:1)
不完全确定Django 1.4是否有适当的JsonListField,我认为可能有一个但不是100%肯定。无论如何,写你自己至少更有趣:)
快速Google至少给了我这两个结果:
看一下get_db_prep_lookup()
方法,你似乎无法轻易做到这一点:
https://github.com/django/django/blob/master/django%2Fdb%2Fmodels%2Ffields%2F__init__.py#L737-L771
def get_db_prep_lookup(self, lookup_type, value, connection,
prepared=False):
"""
Returns field's value prepared for database lookup.
"""
if not prepared:
value = self.get_prep_lookup(lookup_type, value)
prepared = True
if hasattr(value, 'get_compiler'):
value = value.get_compiler(connection=connection)
if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'):
# If the value has a relabeled_clone method it means the
# value will be handled later on.
if hasattr(value, 'relabeled_clone'):
return value
if hasattr(value, 'as_sql'):
sql, params = value.as_sql()
else:
sql, params = value._as_sql(connection=connection)
return QueryWrapper(('(%s)' % sql), params)
if lookup_type in ('search', 'regex', 'iregex', 'contains',
'icontains', 'iexact', 'startswith', 'endswith',
'istartswith', 'iendswith'):
return [value]
elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
return [self.get_db_prep_value(value, connection=connection,
prepared=prepared)]
elif lookup_type in ('range', 'in'):
return [self.get_db_prep_value(v, connection=connection,
prepared=prepared) for v in value]
elif lookup_type == 'isnull':
return []
else:
return [value]
虽然更改值的as_sql
可能会有效,但稍微查看代码会告诉我它可能会赢得
你最好的猜测(这是我过去做过的事情,自从0.95以来一直对我有用)是覆盖Manager
并让它返回自定义{{1 }}修改QuerySet
方法并在查询被重新发送之前重写。