Views - Lesson 3
Tags: django, python, beginners
Published: 2019-06-19 21:22:44

In this lesson, we would be discussing further uses of the views.py file other than just returning an HTML page. To do this we would be building a small app while we make a few changes to the way our current homepage is displayed.

##Changes to Make 
Currently, our Homepage is served from the ***blog*** app, but we should honestly leave the ***blog*** for only blog related things. Meaning we have to move our homepage out, probably to the root directory. The first thing we would do is create a folder called ***templates*** in the ***awesome-project*** directory. Second, move the ***home.html*** file to this newly created folder.

Next, go to ***settings.py***. Around line ***55***, we see ***TEMPLATES***. Inside the list of ***DIRS*** add ***'templates'***, which is the name of the templates folder we created.
So, my line 58 looks like:
```python
    58.        'DIRS': ['templates'],
```
Next, we create a ***views.py*** file inside the ***awesome*** directory. and copy the content from the ***views.py*** inside the ***blog*** directory. You can go ahead and delete the function we created in the previous ***views.py***. And make appropriate changes to the ***views.py*** inside the ***awesome*** directory.
```python
    1. from django.shortcuts import render
    2.
    3. # Create your views here.
    4. def home(request):
    5.     return render(request, 'home.html')
```
> This should be inside ***awesome/views.py***

One more change we should make, assuming I'm not missing anything out, is to the ***awesome/urls.py*** file. Instead of having:
```python
    18. from blog import views
```
We now have:
```python
    18. from . import views
```
>This means - from this directory, import views.

Save all files, run your server and make sure your home page still displays. If it does, let's move on.

![Testing changes made to the site; new home page](https://thepracticaldev.s3.amazonaws.com/i/72hrh1si56fayr17t83m.png)<figcaption>It's not yet time for a carrot 😏.</figcaption>


## Views.py
So to dive into this, we'd be adding a form to our home page that counts the number of vowels in some text. It's a good practice to highlight what would be needed. Thinking of this problem and what we have learnt so far, we would be needing:
1. A form that we use to collect user input;
2. A function that counts the vowels;
3. A page that we return the number of vowels to.

So let us start with no. 1. Adding a form. For the sake of simplicity, we would be adding it to the homepage.
```html
    <form method="POST" action="">
        <textarea name="input-stuff" rows="10" cols="30"></textarea>
        <button type="submit">Check vowel count</button>
    </form>
```
So, here's what my form looks like. Notice I have a method and action on the form tag and a name on my textarea tag. The method is ***POST*** because it's a ***POST*** request. The action is the ***url*** that should be triggered when the button is clicked. We would get back to it. Let's go create our function. 
No. 2
We'd be naming our function counter. and it would look like this:
```python
       # awesome/views.py
    8. def counter(request):
    9.     if request.method == 'POST':
    10.         vow = 0
    11.         for i in request.POST['input-stuff']:
    12.             if i in 'aeiou':
    13.                 vow += 1
```
Most of this code might look familiar, except line 9 and line 11. Line 9 checks if the request method is a ***POST***. A ***POST*** request is basically used when sending certain information to the server. Usually from a form. Line 11, on the other hand, is used to access the information inputted in the textarea. Remember that we named the textarea ***input-stuff***. Well, this helps to access it. One thing we must not forget is that our function must **always** return something. If it doesn't we would most likely get error 500. So the question is: what do we return? Simple. A page to display the result.
No. 3
Let's create an HTML file called ***count*** in the ***templates*** directory. We would be back to what should be inside it in a few. Okay... That's a lot of things on hold. 
1. Action in the form tag.
2. A return statement in the counter function.
3. The content of the count.html file
4. The url that would lead to the counter function.

Let us handle the ***view.py*** first. We need a return statement. Our return statement would return the page and a bit of extra information: the number of counted vowels. How do we do this? Well:
```python
    8.  def counter(request):
    9.      if request.method == 'POST':
    10.         vow = 0
    11.         for i in request.POST['input-stuff']:
    12.             if i in 'aeiou':
    13.                 vow += 1
    14.         return render(request, 'count.html', {'count': vow})
```
Okay. Wait a minute. We recognize that last part ***{'count': vow}*** as a python dictionary. So we could use this to pass extra information back to the page that we are also returning; in this case, the ***count.html*** page. 
One thing we should also address if someone tries to visit the ***count.html*** page without going through the home page. Let's just set it to send them to the homepage. For this, we would need to import redirect.
```python
    1.  from django.shortcuts import render, redirect
    ...
    ...
    8.  def counter(request):
    9.      if request.method == 'POST':
    10.         vow = 0
    11.         for i in request.POST['input-stuff']:
    12.             if i in 'aeiou':
    13.                 vow += 1
    14.         return render(request, 'count.html', {'count': vow})
    15.     return redirect('home')
```
Line 15 gives us what we are looking for. Meaning, if the request isn't a ***POST*** request, it would not encounter the first return statement and would move to the next. The return statement on line 15 says: redirect the user to a url with the name of ***home***. We use the url name, not the html file. Note.

Now, let us move to creating the url. Move over to your ***awesome/urls.py*** file, let's add another path.
```python
    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('', views.home, name='home'),
    23.     path('count/', views.counter),
    24. ]
```
>New path is on line 23. If the comma at the end of line 23 is missing, we would face issues.

This shouldn't be strange. Remember to add a comma to end of every closing bracket. You might also notice that I didn't add a name to the ***count*** url and we would get to that shortly. 
Now let's go to the ***home.html*** file and make one minor addition. We would add the action, which would be the url, which is ***/count/***. And then we head over to ***count.html*** and add some strange stuff to the body:
```html
    <h3> Vowels Counted - {{ count }}</h3>
```
This definitely isn't regular html. However, Django allows us to access the contents of the dictionary we returned using this syntax.i.e. 
```python
{{ dictionary_key_name }}
```
Now run your server and check if your code runs.
Mine doesn't 😫😩. However, because DEBUG = True in ***settings.py***, we see the error has to do with ***CRSF verification failed***. Well Django requires that for every form, there is a 
```python
{% csrf_token %}
```
>CSRF stands for Cross Site Reference Forgery. You should read a little about it.

To prevent againt CSRF, a token is generated on every form submission. So let's go add it:
```html
    <form method="POST" action="">
        {% csrf_token %}
        <textarea name="input-stuff" rows="10" cols="30"></textarea>
        <button type="submit">Check vowel count</button>
    </form>
```
Now save, and try again. Ding! Ding!! Ding!!🛎🛎🛎😁😄
Mine works! If yours does, 🍓🍓 strawberries for you.

![Vowel counter works!](https://thepracticaldev.s3.amazonaws.com/i/i07kj0rkndx11syelol4.png)
<figcaption>Awesome work, <insert your name>. You're the best</figcaption>

One final thing is to test what happens when we change the url from ***count*** to ***counts*** in the ***urls.py*** file. 
```python
    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('', views.home, name='home'),
    23.     path('counts/', views.counter),
    24. ]
```
![404 Django](https://thepracticaldev.s3.amazonaws.com/i/2fjscyhxiv5umae5sbti.png)<figcaption>404 error just by changing count to counts<figcaption>
Trying again, we get a 404 error, because the url changed. To combat this e could use the name of the url. So add a name to the ***count*** url.
```python
    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('', views.home, name='home'),
    23.     path('count/', views.counter, name='count-vowels'),
    24. ]
```
Now go to ***home.html*** and make your opening form tag similar to:
```html
9. <form method="POST" action="{% url 'count-vowels' %}">
```
Only the action changed to what is known as a **template tag**. This basically says: search all the urls we have and see if there's any with the name **count-vowels**. If there is, that is the url we want. And so that works.

As we have seen, the ***views.py*** file controls a number of things. This isn't all we can use it for. We would also be talking about **models** and how we can upload images, maybe a profile picture. 
This would be the end of today's article. I know we've been eating fruits, but here 🍩🍿🍫🍪, give yourself a tasty treat if you choose to. Cheers.

I almost forgot the carrot, here 🥕🥕.
<small>Project can be found [here](https://github.com/JonathanFarinloye/Beginners_Tutorial_Django)</small>
<small>Cover image by <a href="https://pixabay.com/users/yabayee-907690/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=705412">yabayee</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=705412">Pixabay</a></small>