0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django公式チュートリアルのまとめ

Posted at

DjangoはPythonでWebアプリを作成する際によく使われるフレームワークです。パッと見返せるよう公式チュートリアルの大まかな流れをまとめました。
公式チュートリアル:
https://docs.djangoproject.com/ja/5.2/intro/tutorial01/

プロジェクトの作成

django-admin startproject mysite

サーバの起動

python manage.py runserver

アプリの作成

python manage.py startapp polls

アプリのURL

mysite/urls.py と mysite/polls/urls.py でURLを分割管理

mysite/urls.py
from django.urls import path, include

urlpatterns = [
    # ex: http://127.0.0.1:8000/polls/
    path('polls/', include('polls.urls')),
    , ...
]
mysite/polls/urls.py
from django.urls import path
from . import views

urlpatterns=[
	# ex: /polls/
	path("",views.index, name="index"),
	]

アプリのView

上記、path()は以下の views.py の index() につないでいる。これにより、レスポンスが返ってくる。

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

アプリの追加

mysite/settings.py
INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    ...,
]

管理者ユーザーの作成

python manage.py createsuperuser

データベースモデル

データベースモデルの作成。models.ForeignKeyにより他のデータベースと連携

polls/models.py
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')

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

データベースモデルの変更を反映

python manage.py makemigrations polls

データベースモデルの確認

sqlite3 db.splite3
sqlite3> .schema

データベースの更新

python manage.py migrate

データベースの確認

sqlite3> .tables

データベース API

python manage.py shell
対話モード
from polls.models import Question, Choice
q=Question(question_text="Hello", pub_date=timezone.now())
q.save()
c=q.choice_set.create(choice_text='hoge', votes=0)
Question.objects.all()
q.choice_set.all()

Admin Page

python manage.py createsuperuser
polls/admin.py
admin.site.register(Question)

その後、http://127.0.0.1:8000/admin にブラウザでアクセス。ブラウザで Question を変更できる。

template

polls/views.py
from django.shortcuts import render
from .models import Question

def index(request):
    question_list=Question.objects.order_by("-pub_date")[:5]
    context={
        "latest_question_list":question_list,
    }
    return render(request, "polls/index.html", context)
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 %}

Raise 404 error

polls/views.py
from django.http import Http404
from django.shortcuts import render

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})

省略形

polls/views.py
from django.shortcuts import get_object_or_404
from django.shortcuts import render

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

Remove Hardcode URL

polls/urls.py で path() に name 引数を指定することで、テンプレート中からURLを逆引きできる

polls/urls.py
urlpatterns=[
	... ,
	# ex: /polls/5/
	path("<int:question_id>/", views.detail, name='detail'),
    ... ,
]
polls/templates/polls/index.html
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

URL Namespacing

polls/urls.py に app_name = 'polls' を追加することで、どのアプリの views 関数か区別できるようになる。

polls/urls.py
app_name="polls"
urlpatterns=[
	...
polls/templates/polls/index.html
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

requestから値を受け取る

template のタグで name = "choice"、value = "{{choice.id}}" として、formを作成し、polls:voteに渡す。

polls/templates/polls/detail.html
	<form action={% url 'polls:vote' question.id %} method="post">
		{% csrf_token %}
		<fieldset>
			<legend><h1>{{ question.question_text }}</h1></legend>
				{% if error_message %}
					<p><strong>{{ error_message }}</strong></p>
				{% endif %}
				{% for choice in question.choice_set.all %}
					<input type="radio" name="choice" id="choice"{{ forloop.counter }}
						value={{choice.id}} >
					<label for="chice"{{ forloop.counter }}>
						{{choice.choice_text}}
					</label>
					<br>
				{% endfor %}
		</fieldset>
		<input type="submit" value="Vote">
	</form>

method="post" で送信されているので、request.POST から値を取得する。request.POSTは辞書型のように扱うことができる。

polls/views.py
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):
        context={
            "question": question,
            "error_message": "You didn't select a choice!"
        }
        return render(request, "polls/detail.html", context)
    else:
        selected_choice.votes+=1
        selected_choice.save()
        response_url=reverse("polls:results", args=(question_id,))
    return HttpResponseRedirect(response_url)

Generic View

generic.ListView と generic.DetailView を使う場合。

ListView では テンプレートに渡すオブジェクトリストを get_queryset 関数で定義している。また、テンプレート中での名前をcontext_object_name で指定する。

DetailView は model で使用するオブジェクトを指定する。context_object_name は自動でモデルの名前から推定される(Questionquestion )。

polls/views.py
from django.views import generic

class IndexView(generic.ListView):
    template_name="polls/index.html"
    context_object_name="latest_question_list"
    def get_queryset(self):
        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"

generic.DetailView は引数名 pk (primary key) で引数を受け取るので、urls.py で pk を指定する。また、クラスViewでは as_view() を呼び出す。

polls/urls.py
urlpatterns=[
	# ex: /polls/
	path("",views.index, name="index"),
	# ex: /polls/5/
	path("<int:pk>/", views.DetailView.as_view(), name='detail'),
	# ex: /polls/5/results/
	path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
	# ex: /polls/5/votes/
	path("<int:question_id>/vote/", views.vote, name="vote"),
]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?