As you know, model managers can be overriden in Django. It's convenient to add custom filtration method there:
But these custom methods cannot be chained:
Overriding manager doesn't allow it, because after first manager method is invoked (
publishedin this case), we receive queryset as a result, which knows nothing about custom manager methods. So we have to add custom methods to queryset. This can look like this:
class ArticleQuerySet(models.query.QuerySet): def published(self): return self.filter("...") def old(self): return self.filter("...")
Now we need to make manager user this class. In order to do this, let's override manager's
class ArticleManager(models.Manager): def get_query_set(self): return ArticleQuerySet(self.model, using=self._db) class Article(models.Model): # ... objects = ArticleManager()
This allows to make queties like:
Here we invoke
all to get queryset instance, because this time manager doesn't have custom methods -
old. To avoid this, we can make manager look for undefined methods in queryset:
class ArticleManager(models.Manager): def get_query_set(self): return ArticleQuerySet(self.model, using=self._db) def getattr(self, key): return getattr(self.get_query_set(), key)
getattris only invoked when attribute is not found by usual means.
Manager can be further improved to be more generic:
class QuerySetManager(models.Manager): def init(self, queryset_class, args, **kwargs): self.queryset_class = queryset_class super(QuerySetManager, self).init(args, **kwargs) def get_query_set(self): return self.queryset_class(self.model, using=self._db) def getattr(self, key): return getattr(self.get_query_set(), key) # Теперь можно писать просто: # objects = QuerySetManager(ArticleQuerySet) #
In order to check if user is authentcated in test, you can run: from django.contrib.auth import get_user class MyTestCase(TestCase): def test_login(self): self.assertFalse(get_user(self.client).is_authenticated()) self.client.login(username='fred', password='secret') self.assertTrue(get_user(self.client).is_authenticated())
It appears that not everyone knows that in python you can create classes dynamically without metaclasses. I'll show an example of how to do it.So we've learned how to use custom QuerySet to chain requests:Article.objects.old().public()Now we need to make it work for related objects:user.articles.old().public()This is done using use_for_related_fields, but it needs a little trick.
In UNIX way, each view should solve single task. This is good idea, but sometimes we need to mix logic of different views on same page. Filter, sort, paginate, or, for example, add comment on product page. In this article I'll show how we can mix such multiple views.
For any project there may be a need to use a database full-text search. We expect high speed and relevant results from this search. When we face such problem, we usually think about Solr, ElasticSearch, Sphinx, AWS CloudSearch, etc. But in this article we will talk about PostgreSQL. Starting from version 8.3, a full-text search support in PostgreSQL is available. Let's look at how it is implemented in the DBMS itself.