[PYTHON] django tutorial memo

Official tutorial for Django, the python web framework "Creating your first Django app" Notes 1-5.

It's really just a memo.

Click here for the original website https://docs.djangoproject.com/ja/3.1/intro/tutorial01/

1. Installation

Create a python environment and enter with pip

terminal


pip install django

I will check if it is included

terminal


$ python -m django --version
3.1.2

It seems that django 3.1.2 is included

2. Create a Django project

When you run django-admin startproject hoge, it will automatically create the minimum required folders and files for your project.

terminal


django-admin startproject mysite

The created file has the following structure

Directory structure


mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

DB is python standard sqlite3.

For the time being, the sample page can be displayed in this state, so let's try it. Running manage.py runserver will start a simple server for development.

terminal


python manage.py runserver

Since the started server waits on port 8000 of local host, you can see that you can open the following URL with a browser. http://127.0.0.1:8000 image.png

In addition, since this simple server is made only for use during development, it is written in the official tutorial that "Never use it in a production environment". In the production environment, let's publish using Apache etc.

3. Create an application in your project

Django allows you to work with multiple applications. If you execute as follows, the minimum required files for the application will be automatically generated.

terminal


python manage.py startapp polls

Directory structure


polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

You can create as many apps as you like, so it seems that productivity will increase if you divide them well by function.

4. Make a view of polls app

view is written in views.py.

The following is a view that returns "Hello, world. You're at the polls index." On http when you come to read /polls/index.html.

polls/views.py


from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

I will write the association to the above views.py in urls.py.

Write it in django.urls.path () and it will be associated. If you write as follows, you will find index () in polls / views.py by referring to mysite / urls.py → polls / urls.py → polls / views.py in that order.

mysite/urls.py


from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

polls/urls.py


from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

Now that the association is complete, let's start the simple server and check it.

terminal


python manage.py runserver

The contents written in polls / views.py will wait for you in the url. http://localhost:8000/polls/

5. DB change

By default, sqlite3 is used, so you can do it without setting DB. I think that it will be changed to postgreSQL or mySQL in production, so in that case refer to the following. https://docs.djangoproject.com/ja/3.1/intro/tutorial02/

6. Setting TIME_ZONE

The standard is set in UTC

mysite/setting.Before changing py


TIME_ZONE = 'UTC'

If you want to use Japan Standard Time, change as follows

mysite/setting.After changing py


TIME_ZONE = 'Asia/Tokyo'
USE_TZ = True

7. migrate

Build a DB based on the contents of setting.py

terminal


python manage.py migrate

Since django treats DB data as an object, it seems that data handling will be easier. (I'm not sure at this point.)

8. Make a model

polls/models.py


import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

setting.py


INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Make django aware that the model has changed

terminal


python manage.py makemigrations polls

9. use django shell

Although django is designed to be more productive by forcing a tidy directory structure, it has the problem of complicated file connections and the difficulty of seeing what happens when you run a function from django. The django shell is provided to help you check this, and you can run it in the python manage.py shell.

django_shell


>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet []>

django_shell


>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
>>> q.save()

django_shell


>>> q.id
1

django_shell


>>> q.question_text = "What's up?"
>>> q.save()

django_shell


>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

django_shell


>>> q.question_text
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

django_shell


python manage.py shell
In [1]:

django_shell


>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

django_shell


>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>

django_shell


>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

django_shell


>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

django_shell


>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

django_shell


>>> Question.objects.get(pk=1)
<Question: What's up?>

django_shell


>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

django_shell


>>> q = Question.objects.get(pk=1)
>>> q.choice_set.all()
<QuerySet []>

django_shell


>>> q.choice_set.create(choice_text='Not much', votes=0)
>>> q.choice_set.create(choice_text='The sky', votes=0)
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
>>> c.question
<Question: What's up?>

django_shell


>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

django_shell


>>> q.choice_set.count()
3

django_shell


>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

django_shell


>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

10. Create a supervising user

Create a superuser for django project supervision. This superuser is for django, so it's separate from the Linux OS user.

django_shell


python manage.py createsuperuser

Enter your ID and password to complete the registration. This will allow you to log in to the admin page, so start the simple server and log in to the admin page.

django_shell


python manage.py runserver

admin page URL http://127.0.0.1:8000/admin/ admin01.png When you log in, you will see something like the following admin02.png

11. Edit the app from the admin page

polls/admin.py


from django.contrib import admin
from .models import Question

admin.site.register(Question)

The polls app column has been added as below admin03t.png

Click Questions to work with the values in the object image.png

I want to use it well because it is easier to understand than operating from the shell.

12. Add View

Creating your first Django app, part 3 https://docs.djangoproject.com/ja/3.1/intro/tutorial03/

Change the view to open depending on the URL

polls/views.py


from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")


def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)


def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)


def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

polls/urls.py


from django.urls import path
from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

Now when you open python manage.py runserver and the following URL in your browser, detail (), results () and vote () in polls / views.py will be executed respectively. http://127.0.0.1:8000/polls/34/ http://127.0.0.1:8000/polls/34/results/ http://127.0.0.1:8000/polls/34/vote/

Create an index page

Rewrite index () in polls / views.py as follows: Question.

polls/vies.py


from django.http import HttpResponse
from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)


def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)


def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)


def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

13. Make a template

In the above, the screen layout is written directly in views.py, but let's separate the description in template so that it can be easily modified. Write loader.get_template ('polls / index.html') in views.py to read template / polls / index.html.

polls/views.py


from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

polls/templates/polls/index.html


{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

render

If you replace the template reading and rendering with render (), you can write it short, and you can import fewer packages.

polls/views.py


from django.shortcuts import render
from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

14. 404 error display

Causes a 404 to be issued when an exception occurs with try / except.

polls/views.py


from django.http import Http404
from django.shortcuts import render
from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)


def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

get_object_or_404

It is troublesome to try / exclude each time, so I will replace it with get_object_or_404 () which is a function that returns 404 if it fails.

python


from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

15. App namespace

If you specify app_name in polls / urls.py, you can refer to it from the namespace of the app. If you do not do this, the operation will be suspicious when there is a view with the same name in another application, so I think it is better to specify it when creating a view without forgetting.

polls/urls.py


from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

This will change the view reference from detail to polls: detail. Respecify other views as polls: hoge as well.

polls/templates/polls/index.html


{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

16. Write a form

Creating your first Django app, part 4 https://docs.djangoproject.com/ja/3.1/intro/tutorial04/

Add a vote button

polls/detail.html


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

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

<form action="{% url 'polls: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>

You can make a button like this http://127.0.0.1:8000/polls/1/ image.png Since the action of the form is set to "post to the view of polls: vote", create a view corresponding to this.

The view of polls: vote is written in polls / urls.py as follows, so you can write it in polls / views.py.

polls/urls.py


path('<int:question_id>/vote/', views.vote, name='vote'),

Add one of the selected targets and redirect to / polls / results /

polls/views.py


from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Question


def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

I will also write a view of / polls / results / called by redirect

python


from django.shortcuts import get_object_or_404, render


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

17. Use a generic view

It seems that useless descriptions can be reduced by using a general-purpose view.

polls/urls.py


from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

polls/views.py


from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from .models import Choice, Question


class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

It's still going on https://docs.djangoproject.com/ja/3.1/intro/tutorial05/

Recommended Posts

django tutorial memo
Python Django Tutorial (5)
Python Django Tutorial (2)
Python Django Tutorial (8)
Python Django Tutorial (6)
Start Django Tutorial 1
Python Django Tutorial (7)
Python Django Tutorial (1)
Python Django tutorial tutorial
Python Django Tutorial (3)
Python Django Tutorial (4)
Python Django tutorial summary
heroku deployment memo (Django)
Django Polymorphic Associations Tutorial
django oscar simple tutorial
Django memo # 1 from scratch
Python OpenCV tutorial memo
FastAPI Tutorial Memo Part 1
Django Girls Tutorial Note
[Memo] Django development environment
Get started with Django! ~ Tutorial ⑤ ~
pyramid tutorial memo (bank account)
Django development environment construction memo
Get started with Django! ~ Tutorial ④ ~
Django
Get started with Django! ~ Tutorial ⑥ ~
Python Django Tutorial Cheat Sheet
[Learning memo] Django command summary
Django admin screen reverse lookup memo
[Django memo] Failure when installing modal
DJango Memo: From the beginning (preparation)
Django Girls Tutorial Summary First Half
FastAPI Tutorial Memo Part 3 Query Parameters
Stumble when doing the django 1.7 tutorial
Deploy the Django tutorial to IIS ①
FastAPI Tutorial Memo Part 2 Path Parameters
Django Crispy Tutorial (Environment Building on Mac)
gzip memo
Raspberry-pi memo
django update
Django note 4
Pandas memo
sqlalchemy tutorial
DJango Memo: From the beginning (model settings)
Django memorandum
django search
HackerRank memo
Django installation
Python memo
Django Summary
Django test
python memo
Information recording memo using session in Django
graphene memo
Flask memo
pyenv memo
Matplotlib memo
pytest memo
Python memo
Install Memo
React → Ajax → Django on Linux implementation memo