how to Set Multiple Environments in Django

published on: | by cindy In category: Django

At some point you have experienced this well I have.

To prevent this from happening simply create multiple environment.

In this article we will create a basic todo app that displays the tasks created, allow you to create a new task and delete task no longer needed. The todo app will illustrate how to achieve setting different environments in django i.e Production, staging and local environment.

If you are a complete beginner please refer to my previous post on creating Django projects using either pip and virtualenv or pipenv

create project Create the directory for the project, create a virtual environment and activate it.Use pipenv to install django

mkdir todo && cd todo
pipenv --three
pipenv shell
pipenv install django
django-admin.py startproject myapp # name of our project

Create app

cd src
python manage.py startapp todo

Inorder to use the app,register by adding it to installed app in settings.py
INSTALLED_APPS = [
    'todo' # the todo app
]

models

from django.db import models

class Task(models.Model):
    STATUS_CHOICES = (
        ('urgent', 'Urgent'),
        ('normal', 'Normal'),
    )
    title = models.CharField(max_length=250)
    description = models.TextField()
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='normal')
    due_date = models.DateField(blank=False) # a date when the task is due
    due_time = models.TimeField(blank=False) # a time when the task is due

    # not visible to user
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'task'
        verbose_name_plural = 'tasks'
        ordering = ('due_date',)

    def __str__(self):
        return self.title

Registering the Models in Admin Site

Django has a powerful inbuilt admin interface.We can easily view all task, perform delete and create operations from the admin panel.

from django.contrib import admin
from .models import Task 

@admin.register(Task) class TaskAdmin(admin.ModelAdmin): list_display =('title','description', 'status','due_date') list_filter =('status','due_date') search_fields=('title',' description') ordering=['status','due_date']

Create and run Migrations

python manage.py makemigrations
python manage.py migrate

Creating superuser

python manage.py createsuperuser
Username (leave blank to use ''): 
Email address: 
Password: 
Password (again): 

running server python manage.py runserver When you visit http://127.0.0.1:8000/admin/ , you shuld be able to add tasks.

We are not creating the app for admin are we? So lets dive in and start creating views for users.We start by creating a form.

forms.py In todo app create a file and call it forms.py. we will create a model froms.

from django import forms
from django.forms import ModelForm
from .models import Task

creating model forms

class TaskForm(forms.ModelForm): class Meta: model = Task exclude = ('created',)

Views

The todo app will list all the tasks on the homepage.Create and delete task.

We will define the urls in myapp.urls. Do not forget to import views from todo app

from django.contrib import admin
from django.urls import path
from todo import views #import todo views

urlpatterns = [
    path('', views.index, name= 'index'),  #homepage
    path('admin/', admin.site.urls),
    path('create/', views.create_task, name= 'create'), #add task
    path('delete//', views.delete_task, name= 'delete'), #delete task

Views.py We will do a number of imports.we must import our form in forms.py and model.I will use the get_object_or_404 object to get task and task id from the db

from django.shortcuts import render, redirect,get_object_or_404
from .models import Task
from .forms import TaskForm

Create the index logic to display all the tasks in views.py.

def index(request):
    todo_list = Task.objects.all()[:7]
    context = {'tasks': todo_list}
    return render (request, 'todo/task/index.html', context)
Create the create logic to create new tasks

def create_task(request):
    if request.method == 'POST':
        add_form =TaskForm(request.POST)
        if add_form.is_valid():
            add_form.save()
            return redirect('index')
    else:
        add_form =TaskForm()
    context= {'form':add_form}
    return render(request, 'todo/task/create.html', context )

Create the delete logic to create new tasks

def delete_task(request, task_id):
    task = get_object_or_404(Task, id=task_id)
    task.delete()
    return redirect('index')
 

Templates and static files

We have views but no templates to display them and some styling in todo app create directory templates with sub-directories todo inside todo directory we create our base template base.html

Django Multiple Environment

If you are already weary of waiting, the time has come. In myapp, create a folder and call it settings. Inside the settings module create 3 files. 1. base.py # contain common settings 2. local.py # will contain settings relevant for local development 3. prod.py # contain only settings relevant for production

The settings folder is not a python module and to make it one simply add __init__.py file inside it.

Copy settings.py content into base.py then delete it.Import the base settings in both local and deb by doing this:

from .base import *

After importing base settings in local.py I have removed debug= True settings from base.py and added it to local.py DEBUG = True

If you try to run server at this point you should definitely get an error.Django cannot find either of the settings because we have moved them a folder inside.

To resolve this error, in base.py change base-dir from BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) To BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(os.path.join(__file__, os.pardir))))

if we run the server again, we get the error raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty. We have not specified the development settings we we want to use and we can achieve that by 1. Simply adding the environment's settings flag each time you run commands

python manage.py command --settings=myapp.settings.local
2. export DJANGO_SETTINGS_MODULE=myapp.settings.local Then run all other commands as usual

note myapp.settings must be replaced with the project name.The name you used when running the dango-admin.py startproject name.Or simply check this line os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings') in wsgi.py

Conclusion

Thank you for your patience, it was quite a long post.There are so many ways of doing this.I find this method simple.The todo app is basic but tweak it and if you host yours, leave a comment below. This code can be found on Github