Django with DRF – installation cheat sheet – pip & Anaconda

A little “cheat sheet” with the most common commands and settings for starting a new Django project aimed at building a RESTful API with Django REST Framework.
Total
0
Shares
Django + DRF installation cheat sheet

As projects usually tend to spread across many months of development, creating new projects is not something we as developers do often.

So I put together this little “cheat sheet” as a reminder. It contains some most common commands and settings for starting a new Django project aimed at building a RESTful API with Django REST Framework.

Install dependencies

Install Django + DRF with pip:

pip install -U django djangorestframework django-filter drf-yasg

Install Django + DRF with Anaconda

If you prefer more than one snake in your life 😉:

conda install -c conda-forge django djangorestframework django-filter drf-yasg
NOTE: The commands above include drf-yasg for auto-generated Swagger documentation and django-filter for filtering on endpoints. Feel free to skip those if not needed.

Start a new Django project

django-admin startproject myproject .

The dot . at the end indicates that the project files will be created in the folder you’re currently in rather than a new folder.

If you get an error message saying No module named django-admin the following command should help:

python -m django startproject myproject .

Configure database access

PostgreSQL

For connecting to PostgreSQL, you’ll need to install the following package:

pip

pip install -U psycopg2-binary

Anaconda

conda install -c conda-forge psycopg2-binary

Then update the DATABASES object in the settings.py file of your project:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        ... # NAME, USER, PASSWORD, HOST are here
        'PORT': '5432',
    }
}

For more info, such as how to install and configure PostgreSQL on your local machine, check out this article about running a DRF API with PostgreSQL.

MySQL

MySQL connections require the following dependency:

pip

pip install -U mysqlclient

Anaconda

conda install -c conda-forge mysqlclient

Then update the DATABASES object in the settings.py file of your project:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        ... # NAME, USER, PASSWORD, HOST are here
        'PORT': '3306',
    }
}

For more info, such as how to install and configure MySQL on your local machine, check out this article about running a DRF API with MySQL.

MongoDB

MongoDB is not natively supported by Django. There is a good third-party database engine called Djongo, but it’s still in development.

I wrote an article about building a Django app with DRF and MongoDB and what alternatives you have – feel free to check it out for more details.

To install Djongo run the following:

pip

pip install -U djongo pymongo[srv]

Anaconda

conda install -c conda-forge djongo pymongo dnspython

Then update the DATABASES object in the settings.py file of your project:

DATABASES = {
    'default':
        {
            'ENGINE': 'djongo',
            'NAME': '<database-name>',
            'CLIENT':
                {
                    # Access details are put together as one string
                    'host':
                        'mongodb+srv://<mongodb-user>:<password>'
                        '@<mongodb-host>/<database-name>'
                        '?retryWrites=true&w=majority'
                }
        }
}

Create local apps

Here is how to spin up a new local app:

python manage.py startapp myapp

Add DRF and local apps to Installed Apps

Add DRF (and optionally drf-yasg) to the Installed Apps inside your settings.py file. If any of your local apps will have database migrations, don’t forget to include them as well.

INSTALLED_APPS = [
    ...
    'rest_framework',
    # 'rest_framework.authtoken'  # For token auth
    # 'drf_yasg',  # For Swagger
    'myapp.apps.Config',  # Your local app config
]

Something I found quite neat is separating Installed Apps into three separate lists:

  • Django apps
  • Third party packages
  • Local apps

Here’s a snippet if you want to do that:

DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

THIRD_PARTY_APPS = [
    'rest_framework',
    # 'rest_framework.authtoken'  # For token auth
    # 'drf_yasg',  # For Swagger
]

LOCAL_APPS = [
    'myapp.apps.Config',  # Your local app config
]

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

Configure DRF settings

Here is the complete snippet I use as a DRF settings kick-starter. There are also more details for each section further in the article.

REST_FRAMEWORK = {
    # Rendering
    # https://www.django-rest-framework.org/api-guide/renderers/
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],

    # Authentication
    # https://www.django-rest-framework.org/api-guide/authentication/
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # Choose whichever auth you're going to use
        # 'rest_framework.authentication.BasicAuthentication',
        # 'rest_framework.authentication.TokenAuthentication',
        # 'rest_framework.authentication.RemoteUserAuthentication',
    ],

    # Permissions
    # https://www.django-rest-framework.org/api-guide/permissions/
    'DEFAULT_PERMISSION_CLASSES': [
        # Choose whichever permissions you're going to use
        # 'rest_framework.permissions.IsAuthenticated',
        # 'rest_framework.permissions.IsAuthenticatedOrReadOnly',
        # 'rest_framework.permissions.IsAdminUser',
        # 'rest_framework.permissions.AllowAny',
    ],

    # Parsers
    # https://www.django-rest-framework.org/api-guide/parsers/
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
    ],

    # Filtering
    # https://www.django-rest-framework.org/api-guide/filtering/
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],

    # Pagination
    # https://www.django-rest-framework.org/api-guide/pagination/
    'DEFAULT_PAGINATION_CLASS': None,
        # Pagination options:
        # 'rest_framework.pagination.PageNumberPagination'
        # 'rest_framework.pagination.LimitOffsetPagination'
        # 'rest_framework.pagination.CursorPagination'
    'PAGE_SIZE': 20,
}

if DEBUG:
    # Rendering
    REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'].append(
        'rest_framework.renderers.BrowsableAPIRenderer',
    )
    # Authentication
    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append(
        'rest_framework.authentication.SessionAuthentication',
    )

Default Renderer Classes

Django REST Framework uses the following classes as default API renderers:

  • rest_framework.renderers.JSONRenderer and
  • rest_framework.renderers.BrowsableAPIRenderer

But you might want to disable Browsable API in production since it has some security concerns. Here is a snippet to only use it when DEBUG mode is on:

REST_FRAMEWORK = {
    ...
    # Rendering
    # https://www.django-rest-framework.org/api-guide/renderers/
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
    ...
}

if DEBUG:
    # Rendering
    REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'].append(
        'rest_framework.renderers.BrowsableAPIRenderer',
    )

Default authentication classes

By default, DRF uses the following classes for authentication:

  • rest_framework.authentication.SessionAuthentication
  • rest_framework.authentication.BasicAuthentication

But the session auth implies the use of cookies which is not entirely stateless. In production, you’re likely to use some token-based authentication.

Similarly, we can use the session auth only when DEBUG is on since it works well with the Browsable API:

REST_FRAMEWORK = {
    ...
    # Authentication
    # https://www.django-rest-framework.org/api-guide/authentication/
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # Choose any auth to use in production
        # 'rest_framework.authentication.BasicAuthentication',
        # 'rest_framework.authentication.TokenAuthentication',
        # 'rest_framework.authentication.RemoteUserAuthentication',
    ],
    ...
}

if DEBUG:
    # Authentication
    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append(
        'rest_framework.authentication.SessionAuthentication',
    )

Default permission classes

By default, DRF uses rest_framework.permissions.AllowAny class that exposes all API endpoints to the public without any authentication. In most cases, this isn’t what we want.

Here is a snippet to reconfigure it:

REST_FRAMEWORK = {
    ...
    # Permissions
    # https://www.django-rest-framework.org/api-guide/permissions/
    'DEFAULT_PERMISSION_CLASSES': [
        # Choose whichever permissions you're going to use
        # 'rest_framework.permissions.IsAuthenticated',
        # 'rest_framework.permissions.IsAuthenticatedOrReadOnly',
        # 'rest_framework.permissions.IsAdminUser',
        # 'rest_framework.permissions.AllowAny',
    ],
    ...
}

Default parser classes

Django REST Framework uses the three following classes to parse submitted data by default:

  • rest_framework.parsers.JSONParser
  • rest_framework.parsers.FormParser
  • rest_framework.parsers.MultiPartParser

There is no harm in it, but you might want to reconfigure your API to only accept one data format by default and handle other formats on a view level:

REST_FRAMEWORK = {
    ...
    # Parsers
    # https://www.django-rest-framework.org/api-guide/parsers/
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ],
    ...
}

Default filter Backends

DRF doesn’t provide any filtering on endpoints by default, but it’s often desired functionality.

If you haven’t installed django-filter yet, refer to the installation section above for the snippet to install it.

Then configure the filters in DRF settings:

REST_FRAMEWORK = {
    ...
    # Filtering
    # https://www.django-rest-framework.org/api-guide/filtering/
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],
    ...
}

Default pagination class and page size

Since you’ll most likely need pagination in your API at some point, it might be a good idea to configure it straight away:

REST_FRAMEWORK = {
    ...
    # Pagination
    # https://www.django-rest-framework.org/api-guide/pagination/
    'DEFAULT_PAGINATION_CLASS': None,
        # Pagination options:
        # 'rest_framework.pagination.PageNumberPagination'
        # 'rest_framework.pagination.LimitOffsetPagination'
        # 'rest_framework.pagination.CursorPagination'
    'PAGE_SIZE': 20,
    ...
}

Configure URLs

Configure Browsable API

If you’re going to use Browsable API, don’t forget to add its login and logout views to the urls.py file of your project:

...
from django.urls import path, include

urlpatterns = [
    ...
    # Browsable API views
    path('api-auth/', include('rest_framework.urls')),
]

Add Swagger endpoints

To configure Swagger, add the following snippet to the urls.py file (and adjust the parameters):

...
from django.urls import path, re_path, include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

# Init Swagger schema view
SchemaView = get_schema_view(
   openapi.Info(
      title='Your API name',
      default_version='v1',
      description='Your API description',
      terms_of_service='your terms of service url',
      contact=openapi.Contact(email='your contact email'),
      license=openapi.License(name='BSD License'),
   ),
   public=True,
   permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    # Swagger views
    re_path(
        r'^swagger(?P<format>\.json|\.yaml)$',
        SchemaView.without_ui(cache_timeout=0),
        name='schema-json'
    ),
    path(
        'swagger/',
        SchemaView.with_ui('swagger', cache_timeout=0),
        name='schema-swagger-ui'
    ),
    path(
        'redoc/',
        SchemaView.with_ui('redoc', cache_timeout=0),
        name='schema-redoc'
    ),
   ... # The rest of urlpatterns
]

This will add the following four endpoints:

  • A JSON view of your API specification at /swagger.json
  • A YAML view of your API specification at /swagger.yaml
  • A swagger-ui view of your API specification at /swagger/
  • A ReDoc view of your API specification at /redoc/

Why create this cheat sheet?

You might be wondering – why create this cheat sheet when each of those plugins already has excellent documentation?

It’s simple – to save you and me time looking things up across various online resources by assembling the most common commands and settings together.

The intention is to make this cheat sheet a handy resource for everyone and share good practices within the community.

So if you have something to contribute, leave a comment below!

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like