the dawn of yuriko hisory

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

DjangoでミリオンライブキャラクターDBを作成 ~prologue~

目的

DjangoGirlsを終えた段階で作れそうなものを実際に作成していく。
あと個人的にキャラクターまとめを作りたかっただけ ←ここ重要


どんなサイトを作るのか

画面は2枚

メインページ
・検索フォーム
・キャラクター一覧

個別ページ
・キャラクター画像
・キャラクター説明

これだけです。
いきなり難しいページつくってもね?


必要になりそうな知識

メインページ
・検索フォーム
ここが一番の難関ですかね。
できればAPI作成して飛ばしてViewModelで画面は弄るようになんかがよさそうですが
そうなってくるとJavaScriptでもVueかReactあたりを学ぶ必要がありそうです。
とりあえずは一番最後に回すことになるでしょう。

・キャラクター一覧
これは初期表示時は全件表示させるので
まずはそこだけを実装しましょう。
後は検索フォーム時に色々いじることになります。

個別ページ
・キャラクター画像
公式のを引っ張ってきます。著作権とか色々気にしたらアウト

・キャラクター説明
これはモデルを作って管理サイトで投稿したものを表示させるだけです。
あとはレイアウトはHTMLとCSSでごにょごにょしましょう。


作成期間

一カ月までかけたくはないかなーと思っています。
ですが検索フォームをどうするかによりますね。

その他

テストは今のところ作成するつもりはないです。
ただ、今後実際に作成する際にはなるべく書いていく方が良いかとは思っているので
どこかのタイミングでテストコードの書き方も勉強していきます。

作成したものはデプロイまでやりたいですが公開する必要があるのかどうかはわかりません。
コードはGitHubにあげる予定です。
コードの修正事項などあったらどんどんお願いします。


とりあえず簡単になりましたこんな感じで1個目のサイトを作っていきましょう。

DjangoGirlsを終えて次へ

終えてみた感想

少し前に一度さっとやりましたが、
ブログで書くということで一行一行理解するようにやっていきました。
思っていた以上にわかっていなかった部分も見つかり今後もまだまだ学習し続けていかなければなと
チュートリアルとしてのDjangogirlsは非常に優秀なので
ぜひともDjangoに興味を持ち実践する人が増えるといいなと思っております。

次やること

Django Girlsの続きがあります
Introduction · Django Girls Tutorial: Extensions
ですが、全部英語でここまで必要あるのかなーと少し思っているので
一度ここでDjango Girlsでやったことの範囲で簡単なサイトを作成していこうかなと
公式のチュートリアルを触るのもいいんですけどね。

何を作るか

一般的に言語学んだあと作るものと言えばTodoアプリとかが多い気がします。
ですが、あくまでこのブログの方針といいますが
自分がプログラミングをやる方向性は
>アニメやら漫画関係で何か作りたいもの
になるのでそういったもので考えていく方向です。

作るものについては別記事で簡単にまとめていきます。

DjangoGirlsに挑戦 ~フォームを作ろう~

フォームで作ろう

今回で最後です。頑張ります。

Djangoフォーム

フォームを作成していきます。
デフォルトではフォーム用のファイルが作成されていないので作成していきます。

app
└forms.py #追加


以下forms.py

from django import forms //1
from .models import Post

class PostForm(forms.ModelForm): //2

    class Meta: //3
        model = Post
        fields = ('title', 'text',) //4

1. Djangoに実装されてるフォームクラスをインポートします。

2.今回はモデル用のフォームを作成するためにModelsFormを利用しています。
Modelと結びつくためのフォームを作成する際は記述します。

3. class Metaはクラス内の設定を書いていく所の認識をしています。
PostFormクラス内でどういった設定をしていくのかを以下に書いていっています。

4.fieldsはmodelで指定したPostの中のどのフィールドをフォームで使用するのかを指定しています。
今回はタイトルとテキストを指定しています。

フォーム画面の表示

投稿用のページへのリンクをbase.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"> 

    <!-- 追加 -->
    <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
    <!-- ここまで -->

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

class指定については特にきにしなくて良いです。
次にURLを作成します。

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

urlpatterns = [
    url(r'^$', views.post_list),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
    url(r'^post/new/$', views.post_new, name='post_new'), //1
]

1.投稿ページのURLは一意でいいのでpost/new/へのアクセスになってます。
それ以降はいままでと特別変わりませんね。

urls.pyで指定してpost_newをViewで作ります。

from .forms import PostForm

def post_new(request):
    form = PostForm() //1
    return render(request, 'blog/post_edit.html', {'form': form})

1.ここで作成したフォームオブジェクトをテンプレートに渡してあげています。

最後にテンプレートを作成します
以下post_edit.html

{% extends 'blog/base.html' %}

{% block content %}
    <h1>New post</h1>
    <form method="POST" class="post-form">{% csrf_token %} //1
        {{ form.as_p }} //2
        <button type="submit" class="save btn btn-default">Save</button>
    </form>
{% endblock %}

1.formタグ
method="POST" はリクエストにPOSTメソッドを利用することを明示しています。
{% csrf_token %}は CSRF対策です。
CSRFについては別で調べる必要がありますが、
とにかくDjangoではフォーム利用時にはCSRF対策をしないとエラーが発生するので
必ず書きましょう。
ちなみにAjax処理を行う際にもCSRF対策をしないといけないみたいです。
そのうちAjaxを使った処理も行いたいです。

2.as_pは

タグでフォームを作成することを示しています。
画像のような形で出力されます。
as_ulやas_table等もありますし
細かくフォームを設定したければ普通にformから値を持ってくればいいですし
中々Djangoのフォームは便利です。
https://i.gyazo.com/d0b68d06d2d8f7fb146ce598ecb6d569.png


とりあえずこれでフォームページができました。
https://i.gyazo.com/33d9a4a9004c049c4e7b51f4776d780c.png

こんな感じになります。

POST処理

ここまでで表示はできましたが、投稿処理ができていません。
フォームを保存する処理を作成していきます。

ここで作成したViewのpost_newを修正していきます。

from django.shortcuts import redirect

def post_new(request):
    if request.method == "POST": //1
        form = PostForm(request.POST) //2
        if form.is_valid(): //3
            post = form.save(commit=False) //4
            post.author = request.user //5 
            post.save() //6
            return redirect('post_detail', pk=post.pk) //7
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

1. フォーム側でHTTPリクエストをPOSTに設定していました。
もしフォームからリクエストが送られた場合はPOSTになるので以下の処理を
初期表示時はGETが送られるのでelse以下で先ほどまでと同じ処理を行います

2. PostFormのPOSTされた値をformに渡しています。
https://i.gyazo.com/fedf63e08516fdfda5a6709f77c32d7d.png

3.is_valid()はそのままバリデーションの意味です。
ただ、バリデーションの設定はしていませんでしたね。
ですが、Postモデルで指定したものが適用されるので
未入力で送信してみるとエラーが起こります。
今回はバリデーションメッセージなどの細かい部分については触れていません。

4.form.save(commit=False)はコミットせずにPostモデルをpost変数にいれています。

5.Postモデル内のauthorにリクエストを送っているユーザーの値を設定します。
このrequest.userはどこの情報なのかがイマイチわからないです。

6.PostモデルをDBにコミットします。

7. リダイレクトで今回作ったページへと遷移します。
動き自体はわかると思います。

フォームの編集

最後に既存のものを編集するページを作成します。

個別ページ用のpost_detailに実装します。

{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.author %}
            <div class="date">
                {{ post.author }}
            </div>
        {% endif %}

        <!-- ここに追加 -->
        <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
        <!-- ここまで -->

        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaks }}</p>
    </div>
{% endblock %}

urlsの修正

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

urlpatterns = [
    url(r'^$', views.post_list),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
    url(r'^post/new/$', views.post_new, name='post_new'),
    url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'), #追加
]

viewの修正

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form': form})

フォーム作成とほぼ同じです。
今までやったことができていれば難しくありません。


以上をもってdjangogirlsは終了になります。
今後の予定については別の記事で書いていきます。

DjangoGirlsに挑戦 ~アプリケーションを拡張しよう~

アプリケーションを拡張しよう

今回は個別の記事の表示
URLパターンをここで覚えておくとサイト作りに役立ちそう

リンクの作成

post_list.htmlにリンクをはっつけます。

% extends 'blog/base.html' %}

{% block content %}
  {% for post in posts %}
    <div class="post">
      <div class="date">
        書いた人:{{ post.author }}
      </div>
      <h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1> //1
      <p>{{ post.text|linebreaks }}</p>
    </div>
  {% endfor %}
{% endblock content %}

1. {% url 'post_detail' pk=post.pk %}
前半部分はpost_detailのリンクだとみてわかると思います。
pk=post.pkは変数の値を渡しています。
詳しくはURLとView側を見ていくとわかります。

とりあえず今の状態でアクセスしてもpost_detailがないので
エラーが起こってしまいます。
post_detailを作成します。

まずapp/ulrs.pyを修正します。

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

urlpatterns = [
    url(r'^$', views.post_list),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'), //1
]

1.post/までは以前までで理解できます。
(?p[0-9]+)について
?pで変数宣言 pkを受け取ります。
post_list.htmlであったpk=post.pkの値がここに入るわけですね。
[0-9]+については正規表現がわかればある程度理解できると思います
0~9の数字のみで +が一けた以上を表しています。
つまりURLは (省略)/post/5 といった形になります。


URLのパターンができたので、次はView側を作成します。
views.pyに以下メソッドを記述します。

from django.shortcuts import render, get_object_or_404

def post_detail(request, pk): //1
    post = get_object_or_404(Post, pk=pk) //2
    return render(request, 'blog/post_detail.html',{
        'post': post
        })

1.pkは先ほどから出ている変数の値です

2. get_object_or_404はオブジェクトが存在しなかった場合404エラーを返すようにしています。
第一引数に取得するモデル、第二引数に検索する値を入れているので(Post, pk=pk)になっています。
ここでpkで検索していることに疑問を思うかもしれません。(どこかででてたかな?)
pkはDB作成時ににDjango側が自動的に主キーとなるカラムを追加してくれています。
pk=primary keyですね。
なのでそれを使って今まで検索していたのです。

さて、最後にテンプレートの作成をします。
これを作らないと画面表示できませんしね。
post_detail.htmlを作成します。

 extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.author %} //1
            <div class="date">
                {{ post.author }}
            </div>
        {% endif %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaks }}</p>
    </div>
{% endblock %}

拡張テンプレートを忘れずに使用しましょう

1.{% if %} {% endif %}について特別説明の必要はない気がしますが
データがあれば出力して、空欄なら何もif文内の処理はおこないません。
意外とテンプレート側でもifを使うことが多いので慣れるとよさそうです。

以上で画面の表示も完璧になりました。
自称で入力フォームを作成してDjangogirlsは終了です。

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にならってそのままつけています。