Django: Internals series - Gotchas
Hi Everyone. Welcome to Django internal series. Goal of this entire series is to share my experience on understanding the internals of django.
In part 1 of this series we try to understand why its important to understand django internals.
I started using django about an year ago. It’s a part of our company’s technology stack. We love building apps with Django(of course who wouldn’t?). During early stage of using django, I really suck at debugging as I felt django is doing lot of magic under the hood. Few basic questions started bothering me.
- I am declaring all fields in model as class variables. How come I am able to access those as instance variables on any of those model instances?
- What is happening when I access any field of a model instance. For e.g take
a look at
simple_django_model.pysnippet below. There we have single field calledemailof typemodels.EmailField(). Now if try to getuser.emailit should technically returnmodels.EmailFieldinstance right?, but django does some magic and return the exact email address as string[email protected] - How does “class Meta” inside any model affects the model behaviour?
- What does really ‘app’ mean to django?(HINT: Every directory with
__init__.pyis not an app) - How django creates actual model instance from db tables?
And much more basic questions..
These questions made me to dig into source code of django. While doing that Pro Django by Marty Alchin helped a lot.
Note: This Pro Django book is kind of outdated. Its written for django 1.5 . During that time, AppCache was used instead of App Register which is one of the great improvement introduced in django 1.7. App Register is something which deals with how django loads and register every app. We will cover App Register in depth in the upcoming series.
But most of the fundamental design and architecture of django remains same as explained in this book. Its really a great book to read if you are interested in understanding django internals.
Why need to understand django internals anyway?
- Makes debugging pleasant
- To understand some of the advanced python concepts and strategies. So that you can apply it in your own projects
- Can help you in becoming better django developer
- Can help in contributing to django open source
- And of course its fun to know how something works under the hood !!!
Some insights
In rest of this post, I will try to address top 2 questions metioned before.
Note: All code examples are tested using python3.5 and django1.9
Consider the following code snippets.
First one is a simple django model with single email field. In second snippet I
tried to do the same with raw python object just to understand the
importants of models.Model
Question 1
I am declaring all fields in model as class variables. How come I am able to access those as instance variables on any of those model instances?
Analysis
In both the snippets, email attribute is a class variable. But how come I couldn’t
access email as class attribute in django model?. The answer is actually the
way django create Model Class using metaclass called ModelBase. In
ModelBase, __new__ method is overriden to alter the behaviour of the
creation of Model class. In this step all the class attributes are converted to instance attribues (source code link here). Thats the reason we could access
all attributes as instance attributes and not as class attributes in any django model.
Question 2
What is happening when I access any field of a model instance. For e.g take
a look at simple_django_model.py snippet. There we have single
field called email of type models.EmailField(). Now if try to get
user.email it should technically return models.EmailField instance right?, but django
does some magic and return the exact email address as string [email protected]
Analysis
In both the snippets, we tried to access the email attribute from instance of
User model. Technically email attribute is of type models.EmailField. So whenever I
tried to access email field, It should give me EmailField instance like
in second snippet. But django is smart and gives us back exact email addres as
string itself. To understand how it works, consider below snippet(slightly
modified version of second snippet)
Now we are able to get the exact email address instead of EmailField
instance just like in User Model. This feature in python is known as getters and setters(using
__set__ you can set the email address directly). Django uses this feature
behind the scene everytime you set or get any model attributes.
We will of course discuss about “Model creation” and “getters, setters” in much more depth in next part of series which completely deals with internals of only Django model
Please let me know your thoughts in comments.