Django Doctor audits code and auto fixes Django anti-patterns. We checked 666 Django projects for problems hindering maintainability and found that 53% of the Django projects had redundant settings and model field kwargs
- 33% of settings.py had redundant values read more
- 29% had fields in models.py with redundant kwargs read more
There were some intersections - so some projects fell into more than one camp.
By "redundant" we mean the values did not need to be explicitly stated because they're only specifying the value Django would have used by default. Like a driving instructor saying "instead of doing 20mph, please do 20mph." This redundancy makes it hard to spot the signal in the noise - so it's harder for developers to zone in on the important code.
But is redundancy noise? Probably, and in the sample we checked it looks like the redundancy was not on purpose. Some justify it with the Zen of Python "Explicit is better than implicit" - but that does not seem to be the reason why 33% over half of projects did this, because if this was the motivation then shouldn't they be explicitly defining all the Django defaults and all the default field kwargs, not just one or two? Additionally, the Zen of Python also suggests:
- simple is better than complex
- beautiful is better than ugly.
- readability counts
- sparse is better than dense
So the the reason for having redundant settings seems to often be:
- a result of copying and pasting settings from other projects; or
- historically non-default values were later updated, and instead of deleting and using the Django default the dev simply changed
- Things slip though the net during code review. Most people do not know every single Django default setting value as they change over the many versions of Django.
How would you reduce noise? Try our Django models.py refactor challenge.
Django ships with default settings. When
django.conf.settings is imported we're not getting a module, we're getting an instance of
LazySettings. This object is a wrapper around a "holder" of the actual settings. During the normal running of Django the holder first uses the default settings then ingests the values in the file defined by the environment variable
So explicitly setting Django's default values in settings.py does not change how Django operates, but it is additional lines of code the developers must read when maintaining the code. The cost of each extra line is non-zero.
It's easy for such things to slip through the net when a human is reviewing the code because this is a nice example of "searching for a needle in a hackstack", but Django Doctor is a code review bot so cannot miss it:
Similar to Django's default settings, Django's model fields have default kwargs that can be overridden when models area defined. Most of the points highlighted in the previous section are valid here so no need to cover them again.
29% of the projects we checked had explicitly defined kwargs, with
null=False being the overwhelming most common one, but
False by default.
So instead of
class SomeModel(models.Model): some_field = models.CharField(blank=False, null=False)
We can simplify things and do:
class SomeModel(models.Model): some_field = models.CharField()
Models are often dense enough even without redundant kwargs. Less dense models will improve the readability of the file and make developers' lives that little bit better.
So like Don't Repeat Yourself (DRY), we can say Don't Repeat Django (DRD).
Or try out Django challenges.