Python Django Tutorial (4)

This is a material for study sessions. I will explain while following the tutorial of django1.8. https://docs.djangoproject.com/en/1.8/intro/tutorial04/

Since version 1.4 is the latest version of the official Japanese document, there are some differences, but the general flow is the same, so it's a good idea to read it. http://django-docs-ja.readthedocs.org/en/latest/intro/tutorial04.html

Tutorial 1 Tutorial 2 Tutorial 3

Tutorial Summary

Creating a voting form

Source: 99b01e3 49d2e35

First, let's rewrite detail.html for voting according to the original tutorial so that you can vote.

polls/templates/polls/detail.html


<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'poll_vote' question.id %}" method="post">
  {% csrf_token %}
  {% for choice in question.choice_set.all %}
  <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
  <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
  {% endfor %}
  <input type="submit" value="Vote" />
</form>

Since the URL is not namespaced, polls: vote is rewritten to poll_vote.

Since the url named polls_vote has not been defined yet, an error will occur even if you open the browser as it is. For the time being, let's rewrite urls.py and views.py and prepare only the skin.

polls/views.py


...
def vote(request, pk):
    pass

polls/urls.py


urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'(?P<pk>\d+)/$', views.detail, name='poll_detail'),
    url(r'(?P<pk>\d+)/vote$', views.vote, name='poll_vote'),
]

Check the details screen on your browser.

Kobito.eiUclF.png

it is a good feeling. By the way, since the vote function is not implemented, an error will occur if you press the button.

html description

Let's go back a little and explain the code in html. The {% if%} tag has not appeared yet, but error_message is passed in the same meaning, and if there is a value, the block up to {% endif%} is output.

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

The {% csrf_token%} tag is, as the name suggests, a tag for setting the csrf token. It must be set in the <form method =" post "> tag. If you forget to set this tag, a csrf exception will occur.

[wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3% 83% 88% E3% 83% AA% E3% 82% AF% E3% 82% A8% E3% 82% B9% E3% 83% 88% E3% 83% 95% E3% 82% A9% E3% 83% From BC% E3% 82% B8% E3% 82% A7% E3% 83% AA)

Cross site request forgery (abbreviation: CSRF, or XSRF) is one of the attack methods in the WWW.

Specific damages include unintentional posting on bulletin boards and shopping at online shops. In addition, if the Web interface of information devices such as routers and wireless LANs is targeted for attack, there is a concern that the settings of those devices may be changed without permission.

In short. This is to guarantee that the data was sent from the legitimate input page. In order to prevent data from being thrown by POST from other sites, token is embedded in the input page.

Edit view for posts

Source: 49d2e35274bd82

Let's edit the vote function. Even so, it is almost a copy of the original tutorial. The redirect destination is the result page at the head family, but this time I am trying to skip it to the list screen.

polls/views.py


from django.shortcuts import redirect

from .models import Choice
...

def vote(request, pk):
    question = get_object_or_404(Question, pk=pk)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return redirect('index')

A little explanation of the code. selected_choice = question.choice_set.get(pk=request.POST['choice']) There is a description of choice_set, which is a manager for manipulating the Choice model that has a relation to the question object. question.choice_set andChoice.objects.filter (question = question)have the same meaning.

If you don't understand the meaning, please wash it lightly.

The posted value is stored in request.POST in a dictionary-like format. Since the name attribute value of the input tag is choice, you can select it with request.POST ['choice'].

On the next line except (KeyError, Choice.DoesNotExist): Here, I am writing the processing when there is no choice input (KeyError) and when a value other than the choice is thrown (DoesNotExist). In this example, error_message is inserted and the input page is displayed again.

The ʻelse:` clause will come in if you have a successful choice for posting. The votes (number of posts) of the selected choice are incremented and saved, and the jump to the list page is performed.

In the original tutorial return HttpResponseRedirect(reverse('polls:results', args=(p.id,))) Although it is written as, here the redirect function is used. What you are doing is exactly the same.

Result page added

Source: 274bd82 4ecb885

Let's make a proper result page instead of a list screen. As usual, html is a copy and paste from the original tutorial.

polls/templates/polls/results.html


<html>
  <body>
    <h1>{{ question.question_text }}</h1>

    <ul>
      {% for choice in question.choice_set.all %}
      <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
      {% endfor %}
    </ul>
    <a href="{% url 'poll_detail' question.id %}">Vote again?</a>
  </body>
</html>

Next, add the results function to views.py. The content is almost the same as detail, only the html path is changed.

polls/views.py


def results(request, pk):
    obj = get_object_or_404(Question, pk=pk)
    return render(request, 'polls/results.html', {
        'question': obj,
    })

Finally, edit the url and connect the views to complete.

polls/urls.py


urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'(?P<pk>\d+)/$', views.detail, name='poll_detail'),
    url(r'(?P<pk>\d+)/vote$', views.vote, name='poll_vote'),
    url(r'(?P<pk>\d+)/results$', views.results, name='poll_results'),
]

Kobito.utItOF.png

The result page is ready.

Change redirect destination

Since it was supposed to jump to the list page after posting, let's fix it so that it jumps to the result page. Note that unlike the list page, poll_results requires arguments.

polls/views.py


def vote(request, pk):
...
        return redirect('poll_results', pk)

Now you can jump to the result page after posting.

Class-based generic View

Documents → https://docs.djangoproject.com/en/1.8/intro/tutorial04/#use-generic-views-less-code-is-better Class-based View documentation → https://docs.djangoproject.com/en/1.8/topics/class-based-views/

About commonly used views such as model list display, detailed display, template specification, etc. django provides a class-based general-purpose View.

ʻIndex, detail, results` in views.py I'm writing now have a small number of lines, so it may be hard to feel the benefits, but Form is involved like vote etc. and it is a little complicated When it comes to, it becomes a very powerful tool.

I haven't mentioned the Form class in the tutorial yet, so I didn't change the source this time. I will only introduce it while watching the original tutorial.

Class-based view conversion will be done in the next (or next) tutorial, so if you are not interested, please skip it.

TemplateView

Although it is not in the original tutorial, it is a simple View that only sets the template to be used. You can use it just by setting which template to use. Override the get_context method to set the dictionary to pass to the template.

All class-based views must be functionalized using the ʻas_view () `method, as you need to pass the view function to the url.

app/views.py


from django.views.generic import TemplateView


class Index(TemplateView):
    template_name = 'app/index.html'

index = Index.as_view()

It is like this.

Class properties such as template_name can also be passed at the time of as_view. In other words, without changing views.py, apply it like this in urls.py.

app/urls.py


from django.conf.urls import url
from django.views.generic import TemplateView


urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name='app/index.html'), name='app_index'),
]

DetailView

In addition to the template to use, specify which model to use.

app/views.py


from django.views.generic import DetailView

from .model import AppModel


class Detail(DetailView):
    template_name = 'app/detail.html'
    model = AppModel


detail = Detail.as_view()

Of course, this class can also be written directly in urls.py. The template is named ʻobject (and the model name is lowercase, such as ʻappmodel). The acquired object is passed. By default, it is called from urls.py with the name pk. If the object is not found, Http404 will be raised.

ListView

Detail is a single object of a model, while ListView returns multiple objects. Which object to return is specified by passing the queryset property or overriding the get_queryset method.

app/views.py


from django.views.generic import ListView

from .model import AppModel


class Index(ListView):
    template_name = 'app/index.html'
    queryset = AppModel.objects.all()

This class has various customization items such as paging and order.

--

In the original tutorial, the test is explained next, but In the next tutorial, I will take a side road and explain the Form class and ModelForm class.

To the next tutorial

Tutorial Summary

Recommended Posts

Python Django Tutorial (5)
Python Django Tutorial (2)
Python Django Tutorial (8)
Python Django Tutorial (6)
Python Django Tutorial (7)
Python Django Tutorial (1)
Python Django tutorial tutorial
Python Django Tutorial (3)
Python Django Tutorial (4)
Python Django tutorial summary
Python Django Tutorial Cheat Sheet
Python tutorial summary
django tutorial memo
Start Django Tutorial 1
Django 1.11 started with Python3.6
Django Polymorphic Associations Tutorial
Django Python shift table
Try Debian + Python 3.4 + django1.7 ...
[Personal notes] Python, Django
Python OpenCV tutorial memo
[Python tutorial] Data structure
Django Girls Tutorial Note
Cloud Run tutorial (python)
Python Django CSS reflected
Do Django with CodeStar (Python3.6.8, Django2.2.9)
Introduction to Python Django (2) Win
[Python tutorial] Control structure tool
Python
Do Django with CodeStar (Python3.8, Django2.1.15)
Python3 + Django ~ Mac ~ with Apache
Getting Started with Python Django (1)
Get started with Django! ~ Tutorial ④ ~
Django
Getting Started with Python Django (4)
Getting Started with Python Django (3)
Get started with Django! ~ Tutorial ⑥ ~
Install Python 3.7 and Django 3.0 (CentOS)
[Python] Decision Tree Personal Tutorial
GAE + python + Django addictive story
Getting Started with Python Django (6)
Getting Started with Python Django (5)
Until Python [Django] de Web service is released [Tutorial, Part 1]
EEG analysis in Python: Python MNE tutorial
8 Frequently Used Commands in Python Django
Python practice_Virtual environment setup ~ Django installation
python + django + scikit-learn + mecab (1) on heroku
python + django + scikit-learn + mecab (2) on heroku
Run python3 Django1.9 with mod_wsgi (deploy)
Django Girls Tutorial Summary First Half
Deploy the Django tutorial to IIS ①
Install Python framework django using pip
Introduction to Python Django (2) Mac Edition
[Python Tutorial] An Easy Introduction to Python
Learning history for participating in team app development in Python ~ Django Tutorial 5 ~
Learning history for participating in team app development in Python ~ Django Tutorial 4 ~
Learning history for participating in team app development in Python ~ Django Tutorial 1, 2, 3 ~
Learning history for participating in team app development in Python ~ Django Tutorial 6 ~
Learning history for participating in team app development in Python ~ Django Tutorial 7 ~
kafka python
django update
Django note 4