the dawn of yuriko hisory

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

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>

https://i.gyazo.com/5c1c5c6102738eef47e5013d66623af7.png

蒼くなってますね。

何やってるかを確認してみると、タグに色指定してくれています。
[https://i.gyazo.com/5ca4a5be4a9f23ec5c63fe9da2287727.png:image=https://i.gyazo.com/5ca4a5be4a9f23ec5c63fe9da2287727.png]



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

読み込まれていることを確認して
https://i.gyazo.com/d8979c82d9192dd873e76373446edb77.png

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>

表示させてみると
https://i.gyazo.com/47265cc5b6190ca6496656c22a9127e9.png

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>

gyazo.com


だいぶみやすくなりました。
他のフレームワークなんかを使ったことあると何やってるかすごいわかりやすいシンプルな記述法
使ったことなくても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>

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

ブログっぽくなりました。
前にやった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.
クラスからオブジェクトをすべて取得します。

管理サイトで登録した内容が返ってきます
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ファイルへと紐づけられれば基本となる画面遷移はできる