Create Center
Resources:
In this video, we will learn how to create an center object using function based view.
Forms
To perform create and update operation, we need to create forms.
So, first of all, create forms.py file in center app.
In this file, import ModelForm from django.forms. The benefit of using modelform is that, django can generate form by looking at our model. If you want to create a plain form that is not associated with any model then you can use Form from django.forms.
from django.forms import ModelForm
Now, import Center from center.models
from center.models import Center
After that create a class named CenterForm and it inherits ModelForm which we have imported.
class CenterForm(ModelForm):
Now, create Meta class.
class Meta:
In this meta class, we will write two things: model and fields.
Since, we are creating form for Center so, we are writing model = Center.
model = Center
Now, in our Center model, we have two fields. I want to include both the fields, therefore, I will set the value of fields as all.
fields = "__all__"
[Complete Code]
In this way, we have created Center form in django.
from django.forms import ModelForm
from center.models import Center
class CenterForm(ModelForm):
class Meta:
model = Center
fields = "__all__"
Views
Now, lets start creating a view that can handle create operation of center model.
In the views.py file of center app create a new view named "create_center".
def create_center(request):
In this view, we have to handle two different things: first one is GET request and second one is POST request.
- When the user sends GET request, we have to return the form to the user which we have created.
- Once user gets the form, fills it and submits it, then that data will be handled in POST request.
GET
First lets start with the "GET" request. In the view write:
from center.forms import CenterForm
if request.method == "POST":
pass
# GET request
pass
Now, we have to create context dictionary that stores the form which we have created.
context = {
"form": CenterForm()
}
Then, we have to pass that context to the create-center.html file.
return render(request, "center/create-center.html", context)
Now, in the center folder of templates, create a new file named "create-center.html". In that file, we have to create a form with POST method.
<form method="POST" action="">
<button type="submit">Submit</button>
</form>
We will use POST method to send data to the server. If you set action as blank string, then it will send our POST data to the same current URL.
We also need to write csrf_token whenever we are handling POST request in Django.
{% csrf_token %}
CSRF stands for Cross Site Request Forgery and a CSRF token is a security measure used to prevent CSRF attack.
In a CSRF attack, an attacker sends a request to a website on behalf of a logged-in user, without the user's knowledge or consent. This can happen if the user visits a malicious website while logged in to the target site, and the malicious site makes requests to the target site using the user's credentials.
In the center form, we have two fields, name and address. To render this form, we can write
{{ form.as_p }}
This line of code, will render form as a paragraph. Therefore, you don't need to write lable tag, input tag. Everything will be handled by the Django. In case, if you want to customize it, you can refer to the django documentation. But as a begineer, just write form.as_p.
URL Routing
Now, create a url path for the create center view.
path("create/", views.create_center, name="create"),
Also, update the url in center list:
<a href="{% url 'center:create' %}"><i class="fas fa-plus"></i> Create Center</a>
Now run the development server and open "center/create".
POST Request
Now, lets learn how to handle the POST Data from the django.
In the post method we have to create a form and instantiate that form with the POST data.
form = CenterForm(request.POST)
Now, you have to check whether the form data is valid or not:
if form.is_valid():
pass
else:
pass
If the form is valid, you have to save the form by calling the save method.
form.save()
Once, the form is saved, we have to redirect our user to the list page of center.
from django.http import HttpResponseRedirect
Now, in the HTTPResponseRedirect, we have to pass the url to which the user will be redirected. There are actually two ways to pass the URL. One way is just write the url path. But the another and recommended way is to use reverse function.
from django.urls import reverse
In the HTTPResponseRedirect, write
reverse("center:list")
This reverse function will return the url path for center list. The benefit of using reverse function is that, if someone changes the url path for center list, then our code will not break and also, we don't need to memorize or take care of actual url path.
In this way, if the form is valid, we are saving the form data and redirecting the user to center list page.
But if the form data is invalid, we have to redirect user to the same page from where they send the POST request.
Therefore, in the else part, write.
return render(request, "center/create-center.html", {"form": form})
If the form data is invalid, then it will return the create center page along with the instantiated form. This instantiated form also contains error data which you can show it to the user and ask to enter correct value.
[Complete Code]
def create_center(request):
if request.method == "POST":
form = CenterForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("center:list"))
else:
return render(request, "center/create-center.html", {"form": form})
context = {
"form": CenterForm()
}
return render(request, "center/create-center.html", context)
Template
Now, lets start modifying our HTML template to make it look more attactive.
First of all, in the project root template directory create a folder named components.
Now, you have to download form.html file from the resources section and save it inside the components folder.
Also, you have to download create-center.html file and copy its content and paste it in your create-center.html file.
[form.html]
<form method="POST" action="">
{% csrf_token %}
{% for field in form %}
<div class="mb-2 row">
<div class="col-sm-2">
{{ field.label_tag }}
</div>
<div class="col-sm-10 col-md-8 col-lg-6">
{{ field }}
</div>
{% if field.help_text %}
<span class="help offset-md-2">{{ field.help_text|safe }}</span>
{% endif %}
{% if form.errors %}
<span class="offset-md-2">{{ field.errors }}</span>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">{{ form_name }}</button>
</form>
[create-center.html]
{% extends 'mysite/base.html' %}
{% block title %}
<title>Create Center</title>
{% endblock title %}
{% block content %}
<div class="card p-3">
<div class="card-body">
<h4 class="mb-3">Fill the following details to create a new center</h4>
</div>
</div>
{% endblock content %}
[Explanation for form.html]
You might be confused that why I have created a separated folder named components and created form.html file. Actually, we are going to use this form.html in various places of our django templates. Therefore, instead of writing the same form again and again, we will inherit the form code and use it in django templates.
In this form.html file,
- First of all, we have created a form that sends data through POST method and the action is set to be blank, that means, the data will be sent to current URL from where this form will be rendered.
- Then, we have added a csrf token, since we are handling POST data in django.
- After that, we are iterating over every field of the form.
- For every field, we are dislaying the label tag, the field, help text and errors. We don't need to write the actual label tag, the input tag, help text field and error field. Django will handle all this things by itself. We just need to tell, what we have to render and where we have to render.
- At the end, we have created a button that have form_name. We will pass this form_name when we include this file in the django temaples.
[Explanation for create-center.html]
In the create-center.html file,
- First of all, we have extended the base template, then added title block.
- After that, we have created content block where we will write the main content of this page.
Just below the h4 tag, we have to include form.html file of components.
{% include "components/form.html" with form_name="Create Center" %}
In this line of code, we are including the form.html file inside the create-center.html file.
We are also passing extra value to this file and it is the form name = "Create Center".
So, when this code is rendered, it will include the contents of the "form.html" template file, and the included file will have access to the context variable form_name, which can be used to customize the included template based on the value of the variable.
[Run the development server and see the changes.]
Currently, our form is not styled at. So lets try to add some css to our form field. But actually the problem is, the lable and input tag is generated by Django not by us. So, if we wan't to add any css to label and input tag, we need to customize our form.py file.
Open forms.py file from center app.
Now, create a constructor.
def __init__(self, *args, **kwargs):
Inside this constructor, first of all, call the super method.
super(CenterForm, self).__init__(*args, **kwargs)
Now we have to iterate over form fields and add some class in our input tag.
for visible in self.visible_fields():
Set the value of class as "form-control".
visible.field.widget.attrs["class"] = "form-control"
[Complete Code: forms.py]
def __init__(self, *args, **kwargs):
super(CenterForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs["class"] = "form-control"
[Run the development server and see the changes.]
In this way, we have learnt how to handle create operation of center using function based view.