Published: Aug. 21, 2019 by lukemakin |  estimated reading time: 8 minutes
Last time we finished on creating file with our random_code() function and we have created a model in the database. The link to the first part of the article:

The second part let's start with setting up the logic using function based views in

from django.shortcuts import render
from django.shortcuts import redirect
from .models import Code
from .forms import CodeForm
from django.contrib import messages

def discount_view(request):
form = CodeForm(request.POST or None)
if form.is_valid():
code = form.cleaned_data.get('name', None)
code_obj = Code.objects.get(name=code)
except Code.DoesNotExist:
code_obj = None, 'Invalid discount code')
if code_obj is not None:
request.session['discount'] =

return redirect('carts:cart')

So basically if the method is POST, we validate the form. In case of success we assign the passed code within the form to a variable simply named 'code'. In the next step we must check if the code exists in the database. If it doesn't, we'll display a message, that the code is invalid. If it exists, we'll create a session variable with the amount of the discount assigned to the particular code (for further processing) and finally we need to delete the code (so nobody will reuse it).

Let's try to check if we can achieve the result with ModelForm.

class CodeForm(forms.ModelForm):
class Meta:
model = Code
fields = ('name',)

Spoiler! Unfortunately in this case this will not work for us, because in our model we specified the name as unique = True and in this case Django won't do positive validation of the form with a name that already exists. Let's look closer and print out the form errors, the result should look like the one below:


<ul class="errorlist"><li>name<ul class="errorlist"><li>Code with this Name already exists.</li></ul></li></ul>

So let's use the ordinary Form which we can manually configure.

from django import forms
from .models import Code

class CodeForm(forms.Form):
name = forms.CharField()

If we want to have a nicer look, we can add styling to our form. We will use the bootstrap form-control class, change the label and set a placeholder:

class CodeForm(forms.Form):
code = forms.CharField(label="Discount code",
attrs={ 'class': 'form-control',
'placeholder': 'your code here'

  Now that we have our form, let's add it to the template:

<form action="{% url 'codes:discount' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-percent"></i>&nbsp; Submit code

Also in the template we can place the code to display the messages (set in the view to inform about invalid coupon):

{% for message in messages %}
{% if 'info' in message.tags %}
<div class="alert alert-info">
<p class="font-bold">Notice</p>
<p>{{ message }}</p>
{% endif %}
{% endfor %}

For everything to be working, let's just add the for our app:

from django.urls import path
from .views import discount_view

app_name = 'codes'

urlpatterns = [
path('', discount_view, name='discount')

Remeber to add reference to for the project (like this: path('codes', include('codes.urls', namespace='codes')).

This is is it. Please note, that if you have a products app or an item app - you'll need to get the dicount variable passed in with the django sessions and use it in the particular view.

To view additional content login or create a free account
Share your thoughts

No comments yet...

Signup to the newsletter
To get the latest updates from pyplane
© copyright 2019