Python Django 2 Upgrade Tutorial: Common Problems
Tags: python, django, webdev, dev
Published: 2019-08-29 13:59:24

---
title: Python Django 2 Upgrade Tutorial: Common Problems
published: true
tags: python, django, webdev, dev
canonical_url: https://remotedevdaily.com/python-django-2-upgrade-tutorial-common-problems/
---

This tutorial will cover some of the common errors that you encounter when upgrading your Python Django application to Django 2.

I recently upgraded a project from Django 1.11 to Django 2, and after upgrading I was bombarded with a number of different errors. I thought I’d provide a record of the errors I encountered and how I fixed them.

### 1. No module named ‘django.core.urlresolvers’  

In Django, it’s pretty common to use the reverse function to get the path of a url from it’s name.

The problematic line was the following:


    from django.core.urlresolvers import reverse


The **urlresolver** module was removed in Django 2 and can no longer be used. Instead, you can use the **resolve** function from the **urls** module as such:


    from django.urls import reverse


Awesome! One down. Let’s continue.

### 2. missing 1 required positional argument: ‘on_delete’  

Django 2 now requires the on_delete keyword to be specified for foreign key fields that are used in your models.  
 Previously, it would default to models.CASCADE.

In order to resolve this problem, you’re going to need to add the on_delete keyword arguement to every foreign key field. You also need to specify on_delete for the **OneToOneField** as well.

Your options for the on_delete keyword argument include:

- models.CASCADE
- models.PROTECT
- models.SET_NULL
- models.SET_DEFAULT
- models.SET()
- models.DO_NOTHING

You can read about the values you can pass to on_delete in the [Django documentation](https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete).

Here’s an example of what specifying the on_delete keyword looks like:


    my_field = models.ForeignKey(MyModel, on_delete=models.CASCADE)


OK, moving on to the next error.

### 3. Specifying a namespace in include() without providing an app_name  

This error is caused by a change in the api for Django’s **include** function. We need to make sure the **include** function is being passed the correct arguments.

First, you need to go to the urls.py file you are trying to include and add a variable called **app_name**. You can add it anywhere in the file, but I’d recommend putting it at the top after your imports.

    # my_app/urls.py  
    #... your imports  
   
    app_name="my_app"  
   
    # ... rest of your code

Now, go to the urls.py file that includes the other file. You can now add the **app_name** you specified as the second parameter to the include function.

Here’s an example:


    # urls.py  
    re_path(r'^api/my_path', include('my_app.urls','my_app' )),

### 4. There are duplicate field(s) in ‘fieldsets[<x>][<y>]<br></y></x>

In my case, there was an issue with my custom **ModelAdmin** class. It seems Django used to allow duplicate fields before, but now it does not.

Simply remove the duplicate fields from your custom admin class and you shouldn’t have any issues.

### 5. JSONField default should be a callable instead of an instance so that it’s not shared between all field instances.  

This is an issue you will only encounter if you are using PostgreSQL along with the PostgreSQL JSONField.

Basically, Django only wants you to pass a callable as the default value for this field. This is to avoid the default being shared among all objects which could lead to problems in the case of modification.

If your default is **{}** , replace that with **dict**.

If your default is **[]**, replace that with **list**.

### 6. request.user.is_authenticated() TypeError: ‘bool’ object is not callable  

In Django 2, **is_authenticated** can no longer be called as a function. It is a boolean property and you need to call it like a property as follows:

    request.user.is_authenticated

### 7. Optional Changes  

You are probably using the **url** function from **django.conf.urls**. Your code probably looks something like the following:


    from django.conf.urls import url  
    url(r"^books/$", views.BookList.as_view()),

The **url** function is an alias to **django.urls.re_path()** and it’s likely to be deprecated according to the [Django documentation](https://docs.djangoproject.com/en/2.2/ref/urls/#url).

I highly recommend changing to **import re_path** to avoid future issues when the function is in fact deprecated.

Rewritten with **re_path** , the example from above would become:


    from django.urls import re_path  
    re_path(r"^books/$", views.BookList.as_view()),

And that about sums it up. Hopefully this helped you upgrade to Django 2.

If you liked this and want to see similar content, here are some other [python articles](https://remotedevdaily.com/category/python/) I wrote.  
 Perhaps you are using heroku to host your Django project. If so, check out my article on how to [change your python version in heroku](https://remotedevdaily.com/how-to-change-your-python-version-in-heroku/).

Also, if you are interested in reading more awesome articles about being a remote software developer, please consider subscribing to my [mailing list](https://remotedevdaily.com/subscribe/).

Keep on coding!

The post [Python Django 2 Upgrade Tutorial: Common Problems](https://remotedevdaily.com/python-django-2-upgrade-tutorial-common-problems/) appeared first on [Remote Dev Daily](https://remotedevdaily.com).