Help us understand the problem. What is going on with this article?

DJangoのお勉強(1)

More than 1 year has passed since last update.

DJangoを使い始めたので覚書
Djangoのチュートリアルが何をやっているのかについての解説

今回使ったバージョン
pycharm:2017.3.3 (Community Edition)
Django Version: 2.0.2
Python Version: 3.6.3

pycharmにプロジェクトを作る

個人的に、この環境で開発しているので、pycharmでDjangoを動かす為の準備を行う

  1. pycharmを起動して、プロジェクトを作る
  2. Djangoを使えるようにする
    1. (file)-(Setting) : [project:<プロジェクト名>]-[Project interpreter]
    2. 左上の[+]:Djangoを選択(似たような名前があるので、注意。最初が大文字)
    3. (install package)ボタンを押す
  3. DJangoのプロジェクトを作る
    1. 下にある(terminal)タブを押す
    2. django-admin startproject <プロジェクト名>  (testは名前がかぶるので使えない)
  4. テストサーバーを起動してみる
    1. terminalから
    2. cd <プロジェクト名>
    3. python manage.py runserver
    4. ブラウザでhttp://127.0.0.1:8000/にアクセスする

アプリを作る

Djangoでは、プロジェクトの下に複数のアプリがあるという構成になる。
アプリは複数作っもいいし、ひとつでもいい。けど、とりあえずプロジェクトの下のアプリがあって初めてなんかできる状態になる。

アプリは、ターミナルより下記のコマンドで作成する
python manage.py startapp <アプリ名>

アプリを作成すると、プロジェクトルートの下に下記のディレクトリが作られる

<アプリ名>/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

URLディスパッチ

アプリを作っただけでは、アプリにアクセスする事は出来ない。
、、、ので、URLをディスパッチする為のルールを定義する

ディスパッチングのルールは、プロジェクトのurl.pyでアプリに振り分けるルールを定義し、アプリのurl.pyでアプリ内の振り分けを定義する。

チュートリアルでは下記のように定義されている

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

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

は、urlが'polls/'だった場合は、polls/urls.pyを参照しなされという意味。

そのpolls/urls.pyは下記のように定義されている

polls/urls.py
from django.urls import path

from . import views

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

これは、polls/の下に何もない時は、view.pyのindex関数を呼び出すという意味になる
name=で、このURLパターンに名前をつけることが出来る。
ここでつけた名前によって実際のurlを取得する事が出来る

これを確かめるために、サンプルのview.pyを変更してテストしてみる

polls/views.py
from django.http import HttpResponse
from django.urls import reverse

def index(request):
    urlName = reverse('index')
    return HttpResponse("Hello, world. You're at the polls index.{0}".format(urlName))

http://127.0.0.1:8000/polls/
にアクセスすると、下記のように表示される

Hello, world. You're at the polls index./polls/

path()

あらためて、urls.pyのpath()は、下記のインタフェースになっている。
参照django.urls functions for use in URLconfs¶

path(route, view, kwargs=None, name=None)

routeは、urlパターンを含む、文字列、もしくは、gettext_lazy() 関数を指定する事が出来る。
gettext_lazy()については、多言語化に使うみたいだけど、今はよくわかっていない。
routeに指定する文字列には、<>でくくって、viewに渡す変数を指定する事が出来る。
すなわち、urlの一部がviewの引数として渡される。

これを確かめるために、polls/urls.pyとpolls/views.pyを下記のように変更してみる

polls/urls.py
from django.urls import path

from . import views
import re

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:number>', views.subView, name='suburl'),
]
polls/views.py
from django.http import HttpResponse
from django.urls import reverse

def index(request):
    urlName = reverse('index')
    return HttpResponse("Hello, world. You're at the polls index.{0}".format(urlName))

def subView(request, number):
    urlName = reverse('suburl', args=[number])
    return HttpResponse("これはsubViewです。{0} url={1}".format(number, urlName))

この状態で
http://127.0.0.1:8000/polls/1
にアクセスすると、

これはsubViewです。1 url=/polls/1

と表示される

reverse('suburl', args=[number])と、args=[number]が指定されているのがミソ
<int:number>と変数を指定した場合は、reverseに対しても変数のタプルを渡してやらないとreverseが失敗する

pathのroute引数に指定された文字列のうち、<>で囲まれたint:numberの部分において、intは変数の型を示し、numberは変数名を示す。変数の型には下記のものがある
Path convertersを参照

型指定 内容
str パスセパレータ '/'を除く、空でない文字列に一致します。 コンバータが式に含まれていない場合の既定値です。
int ゼロまたは任意の正の整数に一致します。 intを返します。
slug ASCII文字または数字、およびハイフンおよびアンダースコア文字で構成されるスラッグ文字列に一致します。 例えば、building-your-1st-django-siteのようにします。
uuid フォーマットされたUUIDと一致します。 複数のURLが同じページにマッピングされないようにするには、ダッシュを含め、文字を小文字にする必要があります。 たとえば、075194d3-6885-417e-a8a8-6c931e272f00となります。 UUIDインスタンスを返します。
path パスセパレータ '/'を含む、空でない文字列に一致します。 これにより、strのようなURLパスのセグメントではなく、完全なURLパスと照合することができます。

(by google翻訳)

viewは、urlがマッチした時に呼び出されるview関数を示す。
view引数は、ビュー関数またはクラスベースのビューのas_view()の結果です。 また、django.urls.include()でもかまいません。(by google翻訳)

ビュー関数は、このチュートリアルで使われているやり方で、Viewとして定義されている関数を指定する。
この関数の一番目の引数は、HttpRequest のオブジェクトで、第2引数以降は、もしあれば、routeの中で<>で指定された変数になります。

クラスベースのビューのas_view()については、Django でまず覚えたい TemplateView のパターンに、記載されている説明がわかりやすかった。
テンプレートで使うようだけど、今の段階ではpendding。

django.urls.include()は、他のURLconf moduleをここに展開するための指定です。
参照:include()¶
詳しくは、今はやらないけど、<プロジェクト名>/urls.pyで既に使われている。

kwargs
この引数を指定すると、viewにここで指定した値が渡される。
この引数の型は辞書型でなければならない。
でも、今は試さない。

name
既に説明したとおり、このurlパターンに名前をつける。
viewの中ではreverse関数で、urlを参照出来るようになる。
とりあえず、今は、そんな程度の理解。
URL パターンに名前をつけるに書かれているようだ。

url()

path()以外にもurlパターンを定義出来る。
この関数urlは、 django.urls.re_path().にエイリアスされていて、将来廃止される予定。

re_path()

そんなわけでre_path()

re_path(route, view, kwargs=None, name=None)
基本的にpath()と同じなのだけれども、route引数が、正規表現をとれるところが異なる。
route引数は、指定した文字列そのものが、正規表現として扱われるのでr""のようにregex文字列にする必要が無い一方で\を\でエスケープする必要もない。

たとえばpolls/test0,polls/test1,,,,polls/test9などの文字列に一致させる為のデモとして、polls/urls.pyとpolls/views.pyを以下のように書き換える

polls/urls.py
from django.urls import path,re_path

from . import views
import re

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:number>', views.subView, name='suburl'),
    re_path('test[0-9]', views.repathView, name='re_path_url'),
]
polls/views.py
from django.http import HttpResponse
from django.urls import reverse

def index(request):
    urlName = reverse('index')
    return HttpResponse("Hello, world. You're at the polls index.{0}".format(urlName))

def subView(request, number):
    urlName = reverse('suburl', args=[number])
    return HttpResponse("これはsubViewです。{0} url={1}".format(number, urlName))

def repathView(request):
    urlName = reverse('re_path_url')
    return HttpResponse("repathView。{0}".format( urlName))

この状態で、http://127.0.0.1:8000/polls/test1 にアクセスすると、下記のように表示される

repathView。/polls/test0

この結果で分かる通り、urlのうち、特殊文字の部分は実際の値で反映されない。
この場合には、regex文字列でシンボリックグループ名を指定すると反映されるようになる

polls/urls.py
from django.urls import path,re_path

from . import views
import re

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:number>', views.subView, name='suburl'),
    re_path('test(?P<number>[0-9])', views.repathView, name='re_path_url'),
]
polls/views.py
from django.http import HttpResponse
from django.urls import reverse

def index(request):
    urlName = reverse('index')
    return HttpResponse("Hello, world. You're at the polls index.{0}".format(urlName))

def subView(request, number):
    urlName = reverse('suburl', args=[number])
    return HttpResponse("これはsubViewです。{0} url={1}".format(number, urlName))

def repathView(request, number):
    urlName = reverse('re_path_url', args=[number])
    return HttpResponse("repathView。{0} url={1}".format(number, urlName))

http://127.0.0.1:8000/polls/test3 とアクセスした結果は下記の通り

repathView。3 url=/polls/test3

static()

デバッグモードでファイルを提供するためのURLパターンを返すヘルパー関数だそうです

詳細は、django.urls functions for use in URLconfsと[URL ディスパッチャ](https://docs.djangoproject.com/ja/2.0/topics/http/urls/#naming-url-patterns)に記載されているので参照のこと。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away