53% of Django projects have redundant code
Tags: django, python, webdev, codequality
Published: 2021-01-14 17:36:46

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](https://django.doctor/advice/C4005)
- 29% had fields in models.py with redundant kwargs [read more](https://django.doctor/advice/C2002)

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](https://en.wikipedia.org/wiki/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 `True` to `False`.
- 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](https://django.doctor/challenge/models)._

### 1. Redundant settings

Django ships with [default settings](https://github.com/django/django/blob/master/django/conf/global_settings.py). When `django.conf.settings` is imported we're not getting a module, we're getting an instance of [`LazySettings`](https://github.com/django/django/blob/master/django/conf/__init__.py#L49). 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 `DJANGO_SETTINGS_MODULE`.

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.

An implication of this is when we define values in our `settings.py` that are already defined in Django's [default settings](https://github.com/django/django/blob/master/django/conf/global_settings.py) then the action is [idempotent](https://en.wikipedia.org/wiki/Idempotence). To Django, the value may as well not be there.

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:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/01f2kwcipg8advbkx07h.png)


### 2. Redundant field kwargs

Similar to Django's default settings, Django's model fields have [default kwargs](https://docs.djangoproject.com/en/3.1/ref/models/fields/#field-options) 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 [`null` is `False` by default](https://docs.djangoproject.com/en/3.1/ref/models/fields/#null). 

So instead of 
```py
class SomeModel(models.Model):
    some_field = models.CharField(blank=False, null=False)
```

We can simplify things and do:

```py
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)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), we can say _Don't Repeat Django (DRD)_.

### Could your Django be simplified?

Half of Django codebases can be simplified, and it’s easy to miss something during code review. I can check that for you at [django.doctor](https://django.doctor), or can [review your GitHub PRs](https://github.com/marketplace/django-doctor/):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d10epulva9d373jgldhu.png)

Or try out [Django challenges](https://django.doctor/challenge).