utamaro’s blog

誰かの役に立つ情報を発信するブログ

60.DjangoBasicAppsという数年前のプロジェクトのBooksを読んでみる

DjangoBasicAppsのリポジトリは↓です。

https://github.com/nathanborror/django-basic-apps

その中にあるBooksを読んで、Djangoの書き方を確認したいと思いました。

https://github.com/nathanborror/django-basic-apps/tree/master/basic/books

views.pyが見当たらない

見当たらないです。

views.pyが見つからないとか…なんででしょうか。

views.pyがないので、urls.pyを確認してみる

object_detailというのがどこにあるのかみつかりませんでした。

url(r'^genres/(?P<slug>[-\w]+)/$',
    view='object_detail',
    kwargs=genre_list,
    name='book_genre_detail',
),

genre_list自体は↓のように作成されていた。

genre_list = {
    'queryset': Genre.objects.all(),
}

この書き方はあまり使わないですね。

これだとページング処理が入らないし、データを固定にするならtemplateにそのまま書いてもよいです。

views.pyがないので拡張しづらいですね。

それから、as_viewがなくてなぜ大丈夫なのかわかりません。

templateを確認する

templateの書き方を見れるのは嬉しいですね。

これまでどうやって書けばよいのか手探りだったのでわかった気がします。

baseとなるtemplateは↓です。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>{% block title %}{% endblock %}</title>
</head>
<body id="{% block body_id %}{% endblock %}" class="{% block body_class %}{% endblock %}">
  <div id="body">
    {% block body %}
        <div class="content_title">
            {% block content_title %}{% endblock %}
        </div>
        <div class="content">
            {% block content %}{% endblock %}
        </div>
    {% endblock %}
  </div>
</body>
</html>

blockは4つ定義されています。

  • title
  • body
    • content_title
    • content

bookのbaseは↓です

{% extends "base.html" %}
{% block body_class %}books{% endblock %}

book_list.htmlは↓です

{% extends "books/base_books.html" %}


{% block title %}Books{% endblock %}


{% block content_title %}
  <h2>Books</h2>
  {% include "books/_nav.html" %}
{% endblock %}


{% block content %}
    <table class="book_table">
        <tr>
            <th>Title</th>
            <th>Authors</th>
            <th>Progress</th>
        </tr>
    {% for book in object_list %}
        <tr>
            <td class="title"><a href="{{ book.get_absolute_url }}">{{ book.title }}{% if book.prefix %}, {{ book.prefix }}{% endif %}</a></td>
            <td class="authors">{% for author in book.authors.all %}<a href="{{ author.get_absolute_url }}">{{ author.full_name }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
            <td class="publisher"><a href="{{ book.publisher.get_absolute_url }}">{{ book.publisher.full_title }}</a></td>
        </tr>
    {% endfor %}
    </table>
{% endblock %}

content_titleの中にincludeがあります。

includeが使えるのは初めて知りました。

jinja2でもincludeを使えるので当たり前といえば当たり前なんですが。。。

_nav.htmlは↓のようになっていました。

<div id="section_nav">
    <ul>
        <li class="music"><a href="{% url music_index %}">Music</a></li>
        <li class="movies"><a href="{% url movie_list %}">Movies</a></li>
        <li class="books"><a href="{% url book_list %}">Books</a>
            <ul>
                <li class="genres"><a href="{% url book_genre_list %}">Genres</a></li>
                <li class="publishers"><a href="{% url book_publisher_list %}">Publishers</a></li>
            </ul>
        </li>
    </ul>
</div>

階層構造でtemplateを表現するとこのようになります。

  • base.html
    • book_list.html
      • _nav.html

こうやって見るとずいぶんと効率的に書けるとわかります。

ただし、htmlのデザインを書いて、共通化できる箇所を考え、コーディングする技術が必要です。

頻繁にデザインが変わる際は共通化せずに実装し、最終的にリファクタリングする段階で共通化するのが良いでしょう。

headやfooter部分、ナビゲーション部分を共通化するのが良いと思いました。