DjangoGirlsに挑戦 ~テンプレートの拡張~
テンプレートの拡張
テンプレートファイルの作成
HTMLファイルで毎回ナビゲーションやら静的ファイルの読み込みを記述するのは
無断なのでテンプレートファイルを1個作って共通で読み込むものは
管理します。
/app ├templates #追加 └blog ├base.html #追加 └post_list.html
共通ファイルとなるbase.htmlを以下のように記述
基本はpost_list.htmlをコピー
{% load staticfiles %} <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" > <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" > <link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css"> <link rel="stylesheet" href="{% static 'css/blog.css' %}"> </head> <body> <div class="page-header"> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> <div class="content container"> <div class="row"> <div class="col-md-8"> <!-- ここを修正 --> {% block content %} {% endblock %} <!-- ここまで --> </div> </div> </div> </body> </html>
{% block content %}
{% endblock %}
の中身をpost_list.htmlに記述、そのほかはbase.html側で読み込ませるように設定しています。
そしてpost_list.htmlの修正
{% extends 'blog/base.html' %} //1 {% block content %} //2 {% for post in posts %} <div class="post"> <div class="date"> 書いた人:{{ post.author }} </div> <h1><a href="">{{ post.title }}</a></h1> <p>{{ post.text|linebreaks }}</p> </div> {% endfor %} {% endblock content %} //2
1.extendsは拡張、テンプレートの拡張用に記述
その後に読み込ませるbase.htmlの場所を指定してあげます。
これでbase.htmlに書かれている部分を読み込んでくれるようになります。
2.base.htmlで書いた{% block content %}の中身です
{% block 変数名 %}で記述するので、埋め込みたい場所を複数指定もできます。
なのでファイルごとにcss/jsファイルなどを埋め込みたい場合は
base.htmlに{% block static %}とかで指定してpost_list.html側で同じように中身を記述してあげれば
読み込んでくれます。
テンプレートの拡張は複数画面を使うようになると絶対に使用するので、
作るようにすると後後の記述が楽になりますね。
DjangoGirlsに挑戦 ~CSSでカワイくしよう~
CSSでカワイくしよう
カワイ←ここのカタカナがちょっとイラッてなるよね
BootStrap
BootStrapで作ったサイトはBootStrapで作ったんだなと
まあわかってしまうので、デザイン的に好まない人もいそうですが
デザインに深くこだわらなく画面周りを手早く作るならやっぱり使うべきですよね。
djangoのフォーム用にdjango-bootstrap-formとかあったり
pip install django-bootstrap3
普通にpipからインストールしてしまう方法もあるけど
公式のCDNを使ってるのでそのままCDNを使います。
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <! -- ここから --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" > <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" > <! -- ここまで --> </head> <body> <div> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> {% for post in posts %} <div> <h1><a href="">{{ post.title }}</a></h1> <p>{{ post.text|linebreaks }}</p> <p>書いた人: {{ post.author }}</p> </div> {% endfor %} </body> </html>
蒼くなってますね。
BootStrapについては流行っているので日本語の記事いっぱいでてきます。
[http://www.venezia-works.com/edu/index.php:title]ひな形の作成なんかはこういったサイトを使うとより楽できますね。(※Chromeでは使えません)
静的ファイル
静的ファイル中々苦戦しました
しかもデプロイするとまたそれはそれで色々と設定しなきゃいけないらしくほんと静的ファイルマジやばい
STATIC_ROOT = posixpath.join(*(BASE_DIR.split(os.path.sep) + ['static'])) // 1 STATIC_URL = '/static/' //2
1.
STATIC_ROOTは読んでそのままだけどstaticフォルダまでのルートです
デバッグで確認したら
posixpath.join(*(BASE_DIR.split(os.path.sep)
こいつがプロジェクトまでの道のりでその後に静的ファイルが置いてあるフォルダで['static']で指定しているっぽい
アプリケーション側にSTATICフォルダを作って試してみたけど
ちゃんと読み込まれます。ただ、project/app/static/css/hoge.css
みたいな形でおいても
project/static/css/hoge.css にファイルがコピーされてます。
ただDjangoGirlsの通りにproject/static/css/hoge.cssだけ作成しても
どうもファイルを探してくれていないのでアプリケーション側に実装でいいのかな?
今回はアプリケーション配下にcssファイルを実装
マジで静的ファイルのとりあつかいdjangoはめんどくさすぎる
ここだけは本当にDjango嫌い
2.
これはURLの指定先がstatic/以下 になるってことだよね、たぶん
URLルートの作成をしてくれているはず
gyazo.com
/app ├templates #追加 └static └css └blog.css
CSSを記述
h1 a { color: #FCA205; } body { padding-left: 15px; }
HTMLファイルの先頭に以下を追加
{% load staticfiles %}
これは静的ファイルを読み込ませるための者です。
これでCSSはOK反映できました。
静的ファイルの取り扱いはもう少し勉強する必要がありますが。
gyazo.com
後はチュートリアル通りCSS書いていくだけです。
その部分はDjango関係ないので飛ばしていきます。
コピペでいいんですよコピペで
大体こんな感じになってればいいと思います。
DjangoGirlsのCSSの通りにやってもDjangogirlsの画面通りにならない気がする
CSSの指定怪しくない?
gyazo.com
以下HTML
{% load staticfiles %} <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" > <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" > <link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css"> <link rel="stylesheet" href="{% static 'css/blog.css' %}"> </head> <body> <div class="page-header"> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> <div class="content container"> <div class="row"> <div class="col-md-8"> {% for post in posts %} <div class="post"> <div class="date"> 書いた人:{{ post.author }} </div> <h1><a href="">{{ post.title }}</a></h1> <p>{{ post.text|linebreaks }}</p> </div> {% endfor %} </div> </div> </div> </body> </html>
とりあえずこれで静的ファイルの取り扱いは終わりです。
実際に何か作成するときにもっと考えることがありそうですが。
DjangoGirlsに挑戦 ~テンプレートに表示しよう~
テンプレートに表示しよう
長かったDB操作もこれで終わり
今回で取得したデータを表示させます。
Djangoのテンプレートエンジン
Djangoは特別何もいじることなくDjango特有のテンプレートエンジンが使用できます。
ただ、他のPythonフレームワークを使っていてほかの者の方がなじみがある場合は
settings.pyのBACKENDを各々に合わせていじると使えるようになるみたいです。
私はDjango以外使用したことがないので、Djangoのテンプレートエンジンをそのまま使用していきます。
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, },
テンプレートタグを使って表示させてみる
変数を使用するのに{{ }} 二重カッコを使う
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> </head> <body> <div> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> <div> {{ posts }} </div> </body> </html>
Post: 〇〇で表示させている値はモデル内の__str__で設定した値です。
__str__はつまりtoString()でオブジェクトの値を参照した時に__str__で返した値が表示される。
ループ
リストとして表示させるときに一個一個オブジェクトを取得したい時があるので、
一つずつ表示させてみましょう。
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> </head> <body> <div> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> <div> {% for post in posts %} {{ post }} {% endfor %} </div> </body> </html>
だいぶみやすくなりました。
他のフレームワークなんかを使ったことあると何やってるかすごいわかりやすいシンプルな記述法
使ったことなくてもpythonのfor文そのままなのでわかりますね。
postsをfor文で回して一個一個の要素をpostで表示させてるだけです。
少し複雑な表示
これだけだと何を表示させてるのかわからないのでブログっぽくなるように
タイトル、テキスト、投稿者を表示させます。
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> </head> <body> <div> <h1><a href="">the dawn of yuriko hisory</a></h1> </div> {% for post in posts %} <div> <h1><a href="">{{ post.title }}</a></h1> <p>{{ post.text|linebreaks }}</p> <p>書いた人: {{ post.author }}</p> </div> {% endfor %} </body> </html>
ブログっぽくなりました。
前にやったpostだけの表示の場合は__str__で設定したものだけを返していました。
post内のプロパティにアクセスすると、DBで設定した各値が取得できます。
linebreaksはテキスト中の改行を段落に変換してくれますが、今回に限っては特にいみないですね。 |
Djangogirlsにならってそのままつけています。
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.
クラスからオブジェクトをすべて取得します。
オブジェクトの作成
次に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)
特定のキーワードが含まれている場合のfilterは
Post.objects.filter(title__contains='百合子')
titleの次は_が二つです。
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を返している
これで画面上に表示ができるように
テンプレートを扱う
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ファイルへと紐づけられれば基本となる画面遷移はできる