CRUD is the abbreviation used for four major operations performed on a datacenter. These operations usually include the following,

Create

Read

Update

Delete

Every programmer has to deal with these operations at some point. For example, you are developing a social networking website you need to provide the users a way to create their account and read their profile related data. What if they forgot their user name or password? So you surely need to let them update it. Last but not least they don’t want to be active on your site anymore so delete option is required as you surely wouldn’t want your database to be full of inactive users' records. Not only the social networking, but most probably you would need to implement these operations in all of your websites, to some point, at some level.

Let’s make our lives easy and talk about it in this article; the 7th in my Django series. I’m assuming that by far you have pretty good understanding of the Django application. If you have any confusion then refer to the previous articles of the series here.

If you’re wondering why we don't perform the CRUD operations using the admin panel; about which we have talked about earlier in the previous articles; that’s the hardcoded way and is only possible while building. Once you have deployed your site, users will not appear on your doorstep to request an account or update a password. You need to provide users a way to do all that for themselves.

Another way could be by using simple forms but it's a tedious and repetitive part of the job of a developer. You would have to implement a lot of validations; even prefilled fields and so on. Sounds like a nightmare to me not to mention it is an old-fashioned traditional way of doing things. Let’s see what Django has for us in the house.

CRUD using Function-Based Views

Django cares about its ease of use and so is there to help us with its simplified implementation for CRUD operations using Function Based views. These views are easy to read and pretty straightforward. A simple example will help us better understand it.

Let’s say we want to make our site a platform where a user can add their favorite movies. Nothing complex, we’ll just let user add, edit and delete the movies. Let’s get started.

Create a new project by executing the following command.

django-admin startproject CRUD

# CRUD is the name of project

And execute the following command to start app name CRUD_FBVs.

python manage.py startapp CRUD_FBVs

Don’t forget to add your new app to the Installed app. Append CRUD/settings.py as follow,

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'CRUD_FBVs',

]

Let’s start by creating our movie model. Open CRUD_FBVs/models.py and add the following code to it.

We simply defined the model Movies by defining two fields, title and genre. We also defined user as the Foreign Key so that we’ll be able to use the built-in user model. By defining __unicode__() method, Django will call it when it needs to render an object in a context where a string representation is needed. get_absolute_url() method will tell Django how to calculate the canonical URL for an object. In other words, this method will return a string that can be used to refer to the object over HTTP.

We also need to create a simple form to perform the CRUD operations. Create a new python file inside your app and name it forms.py. Append the following code to it.

from django import forms

from .models import Movies

class MoviesForm(forms.ModelForm):

class Meta:

model = Movies

fields = ['title', 'genre']

Function Based views uses decorators to achieve the special functionality. Let’s see how that works. Edit views.py file as follow:

from django.contrib.auth.decorators import login_required

from django.shortcuts import render, get_object_or_404, redirect

from .forms import MoviesForm

from CRUD_FBVs.models import Movies

@login_required

def movies_list(request):

if request.user.is_superuser:

movies = Movies.objects.all()

else:

movies = Movies.objects.filter(user=request.user)

return render(request, 'movies_list.html', {

'object_list': movies

})

@login_required

def movies_create(request):

form = MoviesForm(request.POST orNone)

if form.is_valid():

movies = form.save(commit=False)

movies.user = request.user

movies.save()

return redirect('CRUD_FBVs:movies_list')

return render(request, 'movies_form.html', {'form': form})

@login_required

def movies_update(request, pk):

if request.user.is_superuser:

movies = get_object_or_404(Movies, pk=pk)

else:

movies = get_object_or_404(Movies, pk=pk, user=request.user)

form = MoviesForm(request.POST orNone, instance=movies)

if form.is_valid():

form.save()

return redirect('CRUD_FBVs:movies_list')

return render(request, 'movies_form.html', {'form': form})

@login_required

def movies_delete(request, pk):

if request.user.is_superuser:

movies = get_object_or_404(Movies, pk=pk)

else:

movies = get_object_or_404(Movies, pk=pk, user=request.user)

if request.method == 'POST':

movies.delete()

return redirect('CRUD_FBVs:movies_list')

return render(request, 'confirm_delete.html', {'object': movies})

We imported @login_required decorator which will limit the functionality of the CRUD operations to the logged in user. Remaining code is pretty simple and self-explanatory. You might have noticed the templates mentioned in the above code which we haven’t created yet. Let’s do that. Create templates folder in your app and create the HTML files as follow,

# movie_list.html

<h1>CRUD Function Based View Example</h1>

<ul>

{% for movies in object_list %}

<li>{{ movies.title }} {{ movies.genre }}

<a href="{% url 'CRUD_FBVs:movies_edit' movies.id %}">edit</a>

<a href="{% url 'CRUD_FBVs:movies_delete' movies.id %}">delete</a>

</li>

{% endfor %}

</ul>

<a href="{% url 'CRUD_FBVs:movies_new' %}">Add</a>

#movies_form.html

# movies_form.html

<h1>CRUD Function Based View Example</h1>

<form method="post">

{% csrf_token %}

{{ form.as_p }}

<input type="submit" value="Submit" />

</form>

#movies_delete.html

#confirm_delete.html

<h1>CRUD Function Based View Example</h1>

<form method="post">

{% csrf_token %}

Are you sure you want to delete "{{ object }}" ?

<input type="submit" value="Submit" />

</form>

Now is the time to specify the URLs. Add the following code to urls.py:

That’s it. Now your app is ready to be up and running. Start your server by either executing the following command or directly by running it from your IDE.

python manage.py runserver

You can create superuser and use that to test the functionality or feel free to extend it.

Is there any con?

Function based views are easy to read and simple to implement but there’s also a downside to it. They are hard to customize or extend the functionality. Also they don’t allow the code reuse in true sense so repetitiveness still exists. To deal with all these issues, Class Based Views were introduced.

CRUD using Class Based Views

CRUD operations can be implemented in no time using CBVs, one of the biggest advantages being that if model evolves, changes would be automatically reflected in CBVs if done properly. Thus you can save tens of lines of code by implementing CBVs. They are easily extendable and also allow code reuse. Moreover, Django has built-in generic CBVs which make the life of a developer easy. Let’s implement them and see how the things turn out to be.

We are not going to just dump whatever we have done so far so keep calm. We just need to change our views and urls file as follow.

That’s all for the changes. Now your app can perform all the CRUD operations easily.

Is there any con?

You might have noticed that they are not as readable as Function Based views, mostly because there’s implicit code flow and they apply the Object Oriented technique. One more thing to mention, Class Based Views does not exist to replace Function Based Views. If you’re learning or maybe designing some tutorials for newbies, you might prefer Function Based Views due to their readability. And if you’re deploying your site or working professionally, you might prefer Class Based Views. They both are there for you, it’s up to you to choose which suits your situation.

To Readers

The complete repo of the above example exists on github at my profile. You can download it here. Feel free to experiment with it. You can also contribute to the repo if you want. Happy coding you all. J