the dawn of yuriko hisory

アニメやら漫画関係で何か作りたいものと勉強したことのメモ用

DjangoGirlsに挑戦 ~クエリセット2~

クエリセット2

今回はビュー側での操作です。

クエリセット

models(Post)→view→template
と値を渡していきます

モデルは作り終えてるのでこれをどうやってviewで扱うのかをやっていきます。

from django.shortcuts import render
from .models import Post //1

def post_list(request):
    posts = Post.objects.all().order_by('published_date') //2
    return render(request, 'blog/post_list.html', {'posts': posts}) //3

1.
ディレクトリ内のmodels.pyからPostをimportしています。
これでPostの操作ができるようになります。

2.
Djangogirlsとは変えていますが、とりあえず全データを取得して並べ替えしたものを変数postsに入れているだけです

3.
Postモデルのオブジェクトはpostsに入っていますが、
これをtemplateで扱うにはrenderの引数{}の中に入れてあげればよいのです。
{template側で使う際の命名 : 値}

これでビュー側は終わりです。
{}内は複数の値を渡すことができるので、取得したオブジェクトを変数にいれてその変数を{}内に名前と一緒にいれれば
あとは好きな要素を好きなようにtemplate側に渡すことができます。

あと個人的に複数書くような場合は

render(request, 'blog/post_list.html', {
    'posts': posts,
    'yuriko': yuriko
    })

みたいな形で改行していった方が見やすくて好みです。

DjangoGirlsに挑戦 ~クエリセット1~

クエリセット

今回はPythonファイルをいじりません
データベースの接続方法とデータストアについて学ぶみたいです。
今回学ぶのに意識すべきことは、どうやってモデルからオブジェクトを読み込んだり抽出したりするかでしょうか

オブジェクトの取得

プロジェクトのフォルダからコンソールを開きます。
manage.pyがある場所です。

python manage.py shell

コマンドを入力するとインタラクティブコンソールが起動するので
ここからpythonのコマンドを入力していきます。

from blog.models import Post

Post.objects.all() //1

1.
クラスからオブジェクトをすべて取得します。

管理サイトで登録した内容が返ってきます
https://i.gyazo.com/d8beba66b91b89184667ea33f4e2ba68.png

オブジェクトの作成

次にPostモデルに新しいデータを作成していきます。

from blog.models import Post
from django.contrib.auth.models import User //1

me = User.objects.get(username='yuriko') //2
Post.objects.create(author = me, title = '茜ちゃんもかわいいよね?', text = 'うざい') //3

1.
管理サイト用のUserモデルです。
いつ作ったかと言われると自動的に作られています。
管理サイトにアクセスするためにsuperuserを作ったと思いますが、
その時に登録したものがUserモデルに登録されています。
この辺りはDBに実際につないで値を確認してみると良いです。
パスワードがハッシュ化されて登録などしてくれていたり何かと色々やってくれてます。

2.
変数meの中にUserオブジェクトからusernameに該当するオブジェクトを取得してきています。
usernameはsuperuserを作った際に登録したものが入っています。
これはUser.objects.all()で一回参照すると何を登録しているのかも確認できます。

3.
Post.objects.createはそのままPostオブジェクトに新しいデータを作ってDBに登録しています。
引数に関しては作成したPostを見てみてください。
created_dateはdefaultで登録した現在時刻が入り、
published_dateは空白、nullを許容しているため今回の登録時に省略をしてもエラーになりません。

フィルター機能

getは一つのオブジェクトしか返しません。
実際に
Post.objects.get(author=me)をやってみると
MultipleObjectsReturnedとエラーがでます。

特定の値に該当する複数のオブジェクトを取得するためにはfilterを使います。

Post.objects.filter(author=me)

https://i.gyazo.com/cbc693e489dbbcec5f435e2ec465542c.png

特定のキーワードが含まれている場合のfilterは

Post.objects.filter(title__contains='百合子')

titleの次は_が二つです。

https://i.gyazo.com/644683388518eeacbb0f9b3b14e3b93a.png

並べ替え

SQL分と同じくorder_byで該当するカラムを使ってやればOK
逆順の場合は-をつけて('-created_date')でできます。

Post.objects.order_by('created_date')

ここまでで
CRUDのうちCreateとReadができ
並べ替えもできたので、作成して必要な値を取得して画面に表示ができるようになりました。
後は今回やったような記述をView側で書いて値を取得、レスポンスに返してHTMLで描写すれば
動的なページもできますね。
次回はView側でどうやっていくかをやります。

DjangoGirlsに挑戦~HTMLをやってみよう~

Djangoモデル

テンプレートファイルの作成

テンプレートファイルのディレクトリー構造は以下のようになっている

app
└templates  // ここまでデフォルトで作成される
   └app

Visual Studioでアプリケーション作成時はtemplates配下にindex.htmlが標準で作成されている。
アプリケーション名/templates/アプリケーション名の下にテンプレートを今後記述していくことになるが
これは命名規則によるものらしいけど、未だに違和感がある
なぜこうするのかは今後動かしているうちに理解できるとよいのだが

templates/appの中にpost_list.htmlを作成する

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
 <p> Hello World</p>
</body>
</html>

Djangoに関係ないことだが、Viasul Studioは標準でEmmetが使えるので
html5と打ってTABキーを押すとHTML5のひな形を作ってくれるしHTMLの記述を今後書いていくうえでも楽になるので個人的に好み

何はともあれ前回views.pyに記述したblog/post_list.htmlがこれで作成された。
これでサーバーを起動して確認してみるとHello Worldがばっちり表示されているはず。
ここまでできれば後はリンク張ってつなげれば画面静的なページだけならできますね。

まあ、それだとDjangoを使う意味がなくなるので
次回からDBにアクセスをしてみます。

DjangoGirlsに挑戦 ~Djangoビューってなに~

Djangoモデル

Hello World

ここまできてようやく画面を出すわけだが
Djangogirlsだといきなりテンプレートファイルを読み込んで
表示させるので、そのためのHTMLの作成を挟まなければいけないので
一度Hello Worldで画面描画をしてみようと思う

前回アプリケーションのurls.pyのリクエスト先を指定したので
アプリケーション/views.pyを記述していく

from django.http import HttpResponse

def post_list(request): //1
    return HttpResponse("Hello, World") //2

1.
前回パスを通したpost_listにリクエストが来た時に以下の関数内で処理を行う

2.
HttpResponseでレスポンスにHello, Worldを返している
これで画面上に表示ができるように

https://i.gyazo.com/d28b7bee1a30029cf8bdbe374a7911b4.png

テンプレートを扱う

views.pyをテンプレートを使うようにs郵政

from django.shortcuts import render

def post_list(request):
    return render(request, 'blog/post_list.html', {}) //1

詳しくは次回以降に
リクエスト時にblogフォルダ内のpost_list.htmlを返している
現在HTMLファイルを作成していないのでブラウザを開くとエラーになる

ここまででURLにリクエスト→Viewにリクエストを渡すまでができた
後は実際にHTMLファイルへと紐づけられれば基本となる画面遷移はできる

DjangoGirlsに挑戦~Django urlsってなに?~

Django urlsってなに?

今回デプロイは飛ばします。
実際に何か作る際に改めて調べる必要がありそう。

DjangoのURLはどのように動いているのか

プロジェクトフォルダ/urls.py

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
]

前回の記事で大部分は説明したので飛ばしていきます。

今回はアプリケーションごとにURLの設定をしていきます。
まずはDjangoが起動したときに最初に読み込まれるのは
プロジェクトフォルダのurls.pyに設定されているため
そちらにアプリケーションのurls.pyを読み込ませるように設定する。

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),

    url(r'', include('blog.urls')), //1
]

1
これはURLのパス部分が/ の時にblogアプリケーションのurlsを読み込むように設定している
ローカル環境で接続する場合はhttp://127.0.0.1:8000/にリクエストを送ったときに見てくれる用になる

これでアプリケーション用のURLの設定ができるようになるが、
Djangoのアプリケーションを追加した際にデフォルトでurls.pyは作成してくれていないため、(これはなんでだろう?)
作ってあげる必要がある

project/
├ manage.py
├ app/
│   ├ __init__.py
│   ├ settings.py
│   ├ urls.py
│   └ wsgi.py
└ blog/
     ├ migrations
     ├ _init_.py
     ├ admin.py
     ├ models.py
     ├ tests.py
     ├ views.py
     └ urls.py //ここに新規で追加

blog/urls.py

from django.conf.urls import include, url
from . import views //1

urlpatterns = [
    url(r'^$', views.post_list), //2
]

1.
同フォルダ内のviews.pyを読み込む
なぜ読み込んでいるのかは2で説明

2.
第二引数views.post_listの意味は
このURLにリクエストした時にviews.pyのpost_listを返すように設定している。
DjangoのURLのリクエストの順番として
プロジェクトのurls.py → アプリケーションのurls.py → 表示するようのview(MVCで言うController)に渡して
実際に画面の描写する処理を作成していく


これでとりあえずURLを作成していく流れができたので
次にビュー部分を実装していき、実際に画面に表示させていく。

DjangoGirlsに挑戦~ログインページを作ろう~

ログインページを作ろう

admin(管理ページ)

管理ページに行く前に設定することが二つ

まず一つ目、Visual Studio上でDjangoを作成しているせいなのかわからないが
urls.pyがコメントアウトされているのでadminページへのURLが設定されていません。
なので設定してあげる

プロジェクトのフォルダ/urls.py

from django.conf.urls import include, url //1
from django.contrib import admin //2

urlpatterns = [ //3
    url(r'^admin/', include(admin.site.urls)),  //4
]

1.
URL定義用のクラス
この辺りのクラスはいまいち理解できていない
興味がわいたらソースコードを見てみる

2.
今回作るadmin(管理)サイトのインタフェース
admin配下に管理サイト用のテンプレートやらビューやらが全部あるので
これ見るだけでもかなり勉強になりそう

3.
urlpatterns
関数でもなんでもないけどどこで読み込まれるのか
settings.pyのROOT_URLCONFに設定されてます。

4.
url()の引数の中にごにょごにょ書いていく
引数として(regex, view, kwargs=None, name=None)を受け取る

regexは、正規表現でURLの指定を行う
r'^admin/' これはしばらくは書き方だけ覚えちゃうのが良さそう
細かい設定とかする時になったら改めて覚えるってことで
とりあえずは r''でURLをくくる
^が始まりで/が終わり
つまりr'^admin/'は (URL省略)/adminにURL設定しますよー

viewは、そのままビュー!って思ったら間違い
DjangoはMTVモデルでModel-Template-Viewになっている
通常のMVCでいうとMは同じでDjangoのViewがContoroller、TemplateがMVCのViewにあたる
なのでurlの引数として渡すviewも実際はコントローラの関数に該当する
今回はinclude()でadmin内のurls.pyを見てそこから先はそっちで処理をするようになっている


一つ目がだいぶ長くなってしまったけど
二つ目の設定
今度は表示したいmodelのあるアプリケーションフォルダのadmin.pyを設定
DjangoGirlsだとblog/admin.pyになる そもそも一つ追加してないしね

from django.contrib import admin
from .models import Post //1

admin.site.register(Post) //2

1.
.を使うことで相対パス読み込みになる
.modelsは同ディレクトリ内のmodels.pyを読み込む宣言

2.
adminへの登録
第二引数にadminオブジェクトを作成してadminのオプション変更ができるみたい
使う機会あるかな

設定はこれで終わり
サーバを起動して、ローカルアドレスの後ろに/adminを入れてアクセスすると
https://i.gyazo.com/89d565ba0dec84a2e33ceaab711ff4bf.png

ログインするのにsuperuserを作成する。
Visual Studioなら(以下略)

Djangoの管理画面が優秀すぎてこれだけでおなか一杯になれるし、
ブログで公開する必要なければローカルで管理サイトだけ置いとけばいいんじゃないかなってぐらい
とりあえず作り終わったら今後のためにいくつかポストしておく

https://i.gyazo.com/309f7e3680dd3e937c690c7f2eeacdd5.png

gyazo.com

DjangoGirlsに挑戦~Djangoモデル~

Djangoモデル

DBは標準のsqlite3を使用

アプリケーションの作成

Visual StudioだとDjangoアプリの追加で簡単に作成できる
blogを作成

以下ディレクト

project/
├ manage.py
├ app/
│   ├ __init__.py
│   ├ settings.py
│   ├ urls.py
│   └ wsgi.py
└ blog/
     ├ migrations
     ├ _init_.py
     ├ admin.py
     ├ models.py
     ├ tests.py
     └ views.py

アプリケーション追加後はそれをDjangoで使用できるようsettings.pyを修正

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'blog', #追加
]

モデルの作成

blogアプリケーションからDBを操作するためのモデルを作成
Django girlsではブログを作成していくので
投稿する内容が入るPostモデルを作成

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

class Post(models.Model): //2
    author = models.ForeignKey('auth.User') //3
    title = models.CharField(max_length=200) //4
    text = models.TextField() //5
    created_date = models.DateTimeField(default=timezone.now) //6
    published_date = models.DateTimeField(blank=True, null=True) //7

    def publish(self): //8
        self.published_date = timezone.now()
        self.save()

    def __str__(self): //9
        return self.title

1.
from 〇〇 import ××は
django.dbの中のmodelsメソッドだけを呼びますよーって宣言
普通にimport django.dbでも問題ないけどその場合

import django.db

class Post(django.db.models.Model):
    author = django.db.models.ForeignKey('auth.User')

とかってなって非常に面倒くさいのでfrom importを使って宣言することが多い

2.
class宣言したPostオブジェクトがモデルになる。
django.db.models.Modelを使用することで、Djangoのモデルとして扱う


3.
モデルに対してプロパティを定義
設定したものがそのままDBにも定義される
models.ForeignKey()は引数に渡したモデルへのリンク
('auth.User')はDjangoが元から作成しているUserクラスをリンクしていることになる
Userの追加方法は後ほどやることになる

4.
modelsCharField() 文字列を扱うmax_lengthは必須項目なので忘れるとmakemigration実行時にエラーが吐かれるので注意

5.
models.TextField() テキストを扱うがCharFieldと違って制限なしの長いテキストを取り扱う
ブログ記事などの文章を取り扱う際に使用することになる

6.
models.DateTimeFiled(default=timezone.now) 日付と時刻を扱う
同じようなものでDateFieldがあって混同するが
DateFieldはDatetime.dateインスタンスによって表示される
DateTimeFiledはDatetime.datetimeインスタンスによって表示される
つまりDateFieldは日付、DateTimeFiledは日付+時刻になる
ブログなどの書いた時刻がわかった方が良いコンテンツはDateTimeFiledを使用する
(default=timezone.now)はデフォルトの値にそのまま現在の時刻を突っ込んでいるだけ

7.
blank=True DB登録時に空白を許可
null=True DB登録時にnullを許可

8.
モデル内だけど関数
selfはクラスのインスタンス自身を表しているらしい

def publish(self): //8
    self.published_date = timezone.now()
    self.save()

ざっくりとメソッドの動きはpublished_date(投稿日)を今の時間にセットして
save()でDBに登録してるんだなとわかる
実際にどう動いているかは登録処理時にわかるかな?

9.
__str__でクラスを文字列化している
JavaとかのtoString()をイメージするのがよさそう

テーブル作成

makemigrationとmigrate
VSならボタンポチポチで終了