Chapter 5: New Listing Page - Django 3...2...1...Takeoff! Series 
Tags: django, python, webdev, tutorial
Published: 2020-09-17 01:44:03

Now that all the listings that we created are being displayed, we can go ahead and create a form for users to enter their own listings.

Follow the same creation process as before URL > form > view > template. As you can see, we have added form to the usual process of creating pages. We need to take care of this extra step because we need a form that users will fill out.

**New Listing URL Path**

Go to urls.py in the app’s folder and add the path for the new listing page.

![Screen Shot 2020-09-16 at 8.36.15 PM](https://dev-to-uploads.s3.amazonaws.com/i/dfvflg2altsvyk21zt2s.png)
 
**New Listing Form**

Let’s create a file named forms.py inside the app’s folder. After you create forms.py, the app’s folder tree should look like the screenshot below.

 ![Picture1](https://dev-to-uploads.s3.amazonaws.com/i/s0fcmjbc7ujc21ss3h7l.png) 

Open forms.py and add the following code.

![Screen Shot 2020-09-16 at 8.37.04 PM](https://dev-to-uploads.s3.amazonaws.com/i/343qtmgiar2iylhs8j30.png)

**from django import forms**

Django provides us with a module called forms. This module allows the creation of forms by providing us with the ModelForm class. 

**from .models import Listings**

We will create the form from the Listings model. That’s why we import it here because we need the data in this model.

**class Meta**

We use the class Meta to configure the form in relation to the model (Listings).

The fields of the form have been specified as shown in the list above; notice that we haven’t included the address field because this information is a little sensitive to display online.

**New Listing View**

Open views.py and add the following code.

![Screen Shot 2020-09-16 at 8.37.54 PM](https://dev-to-uploads.s3.amazonaws.com/i/7s29vx655bitdu4vixzo.png)

Let’s describe what is happening in the code. At first sight, you can see that we defined our function and used if and else statements to render the form and allow users to submit data.

**if request.method != 'POST':
        form = form_name()**
 

Since we are submitting data to be processed, we use a POST request. However, in this snippet of code, we are saying that if request.method is not equal to POST, then render an empty form. 

The reasoning behind writing it this way is that in order to access the form in the first place, users will always request data from the server first. When you access the page where the form is located, you are actually requesting the server to show you that page and that’s a GET request.

**else:
        form = ListingForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('listings:all_listings')**

The user has the empty form in front of them, once they fill it out, and submit it. This is the code that will run. There’s a lot to unpack here, so let’s break it down even further. 

**form = ListingForm(request.POST, request.FILES)**

We create a variable form which will hold the data being submitted by the user. We have request.POST which takes care of the data, but we also need request.FILES because we have files as well, in this case image files being submitted. 

**if form.is_valid():**

This statement helps us check if the information in the form is valid by using the is_valid() method. This method checks many things such as that all required fields are filled out, the max length for the fields, data matching field types, and more.

**form.save()**

If the if statement proves to be true, only then we use save() to write the data from the form to the database.

**return redirect('listings:all_listings')**

This one is self-explanatory. After all the information in the form has been checked and submitted, we proceed to redirect users to the main page where all listings are posted. You can redirect users to any other page if you prefer.

**context = {'form': form}
return render(request, 'listings/new_listing.html', context)**

We still need the data stored in the form variable. We need this data in the new_listing template, so that we can display the form. We store the form variable in a dictionary and pass it to the new_listing template which we will create after this step in order to render the form correctly.

**New Listing Template**

The final step is to render the form in the template. Go ahead and create a template in the templates folder. I have called mine new_listing.html, but feel free to choose your own names.

Open new_listing.html and add the following code.

![Screen Shot 2020-09-16 at 8.39.54 PM](https://dev-to-uploads.s3.amazonaws.com/i/ukz0sq8m2fhcay2o49uf.png)

This template is different from the ones that we have created so far, so let’s break it down.

**form action="% url 'listings:new_listing' %" method='post' enctype="multipart/form-data"**

The action argument is sending the data to the URL for the view function new_listing. Thie view is where the data would be processed. The method argument defines what kind of request we are submitting, in this case POST. We also need enctype="multipart/form-data" because we are sending image files. If we don’t include this, request.FILES will be empty. If you are submitting only data, then you don’t need enctype.

**csrf_token**

The Cross Site Request Forgeries (csrf) token is a security measure which needs to be included for any POST form.

**form.as_p**

The built-in template tag **form** already takes care of displaying the labels and input fields of the form. We added as_p to the form in order to display the form fields wrapped in paragraph tags.

Issue the python manage.py runserver command and go to http://127.0.0.1:8000/new_listing/ to see the form.

![fs](https://dev-to-uploads.s3.amazonaws.com/i/yl69t9usnbb6qoe01hqi.png)
 
If you don’t see the form, go back through the chapter and fix any bugs you might have. Try out the form by creating a few more listings. After you submit the form, you should be redirected to the listings page where you can see the new listings being added. 

If you're enjoying the series and want to support, you can find the entire book below.

[*Django 3…2…1…Takeoff! Kindle*
](https://www.amazon.com/Django-Takeoff-Quick-Learning-Development/dp/B08HB1CWHW/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr=)

[*Django 3…2…1…Takeoff! Paperback*
](https://www.amazon.com/Django-Takeoff-Quick-Learning-Development/dp/B08HB1CWHW/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr=)