Overriding get() method in models
Given the poll app example in the Django tutorial. You can perform a get
operation to fetch poll
questions from the database.
In : Question.objects.get(pk=1)
Out: <Question: Question object>
This blog post shows how to override that method. It is not on the model itself. Question.objects
gives you the manager.
In : Question.objects
Out: <django.db.models.manager.Manager at 0x10d3b8860>
You can drop in a custom manager in your models.py.
class QuestionManager(models.Manager):
pass
class Question(models.Model):
objects = QuestionManager()
which results in...
In : Question.objects
Out: <app.models.QuestionManager at 0x107456e48>
But we are not quite there yet. Question.objects.get is doing some delegation magic and actually calling get on an instance of QuerySet. We can replace
class QuestionQuerySet(models.query.QuerySet):
def get(self, **kwargs):
print('hello world')
return super().get(**kwargs)
class QuestionManager(models.Manager.from_queryset(QuestionQuerySet)):
pass
Voilà!
In : Question.objects.get(pk=1)
hello world
Out: <Question: Question object>
References:
- https://docs.djangoproject.com/en/1.10/topics/db/managers/#from-queryset
- https://docs.djangoproject.com/en/1.10/ref/models/querysets/#get
Note that more modern Django versions (since 1.7), provide an easier way to do this. Check out the as_manager()
QuerySet method.
https://docs.djangoproject.com/en/2.2/topics/db/managers/#creating-a-manager-with-queryset-methods
get
isn't a method on the model - you access it via objects
, so it's a method on the Manager. See the official Manager documentation.
The way you have defined the method signature, the request is available as args[0]
.