Django ORM is not a silver bullet, there is nothing wrong with writing parts of SQL if processing with a simple ORM is difficult or impossible. This is a really good use case for extra() :
Entry.objects.extra(where=['"hello" LIKE CONCAT("%%", name)'])
Please note that since we are writing plain SQL here, this will be relevant to the database anyway. This particular mysql type is specific and based on this topic: MySQL: what is the reverse version of LIKE? . It should work for PostgreSQL (not tested).
Please note that you can adapt the request to reusable custom Lookup (introduced in Django 1.7):
imagine you have the following model
class MyModel(models.Model): name = models.CharField(max_length=100) def __unicode__(self): return self.name
Define the Lookup class with the implemented as_sql() method:
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)
then this is how our custom __ce search works in the shell :
>>> 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`)'
Another option is to do a check in Python. Since the LIKE query will do a full scan of all the records inside the Entry table, you can get them all and check them one by one using Python endswith() :
[entry for entry in Entry.objects.all() if 'hello'.endswith(entry.name)]
source share