Django允许我这样做:
chair = Chair.objects.filter(name__endswith='hello')
但我想这样做:
chair = Chair.objects.filter(name__isendof='hello')
我知道查找__isendof
并不存在。但是我想要这样的东西。我希望它与__endswith
相反。它应该找到所有主席'hello'.endswith(chair.name)
。
Django可能吗? ORM操作比SQL操作更好。
答案 0 :(得分:6)
Django ORM不是一个银弹,在编写部分SQL时没有任何问题,因为使用普通ORM进行处理很困难或不可能。这是extra()
的一个非常好的用例:
Entry.objects.extra(where=['"hello" LIKE CONCAT("%%", name)'])
请注意,因为我们在这里编写纯SQL - 无论如何它都是数据库后端特定的。这个特定是特定于mysql的,基于这个主题:MySQL: What is a reverse version of LIKE?。也应该适用于PostgreSQL(尚未测试)。
请注意,您可以将查询调整为可重用的custom Lookup
(在Django 1.7中引入):
假设您有以下型号
class MyModel(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
使用Lookup
方法定义as_sql()
类:
class ConverseEndswith(models.Lookup):
lookup_name = 'ce'
def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return '%s LIKE CONCAT("%%%%", %s)' % (rhs, lhs), params
models.Field.register_lookup(ConverseEndswith)
然后,以下是shell
中自定义__ce
查询的工作方式:
>>> import django
>>> django.setup()
>>> from myapp.models import MyModel
>>> for name in ['hello', 'ello', 'llo', 'test1', 'test2']:
... MyModel.objects.create(name=name)
>>> MyModel.objects.filter(name__ce='hello')
[<MyModel: hello>, <MyModel: ello>, <MyModel: llo>]
>>> MyModel.objects.filter(name__ce='hello').query.__str__()
u'SELECT `myapp_mymodel`.`id`, `myapp_mymodel`.`name` FROM `myapp_mymodel` WHERE hello LIKE CONCAT("%", `myapp_mymodel`.`name`)'
另一种选择是在Python中进行检查。由于LIKE
查询将对Entry
表中的所有记录进行全面扫描,因此您可以全部扫描并使用Python endswith()
逐个检查:
[entry for entry in Entry.objects.all() if 'hello'.endswith(entry.name)]
答案 1 :(得分:1)
如果你有可能使用Django 1.7,你可以使用custom lookups。否则,我认为您必须使用.extra
或.raw
。
答案 2 :(得分:0)
可能就像你要得到的一样......即使它不是很棒
target_string = "hello"
chair = Chair.objects.filter(name__in=[target_string[-i:] for i in range(len(target_string))])