Django is 何【ブログリレー2020summer 12日目】

プログラミング ブログリレー'20夏

この記事はブログリレー2020summerの12日目の記事です。


15期PGのsaruです。

Ruby on Railsの実践的な記事があったので、こちらもDjangoについて簡単に書いて見ようと思います。

自身の認識の整理も兼ねたものなので、大雑把で不十分かもしれませんが、Djangoって何?という方は気軽に読んでみてください。

Djangoとは?

Djangoは、Web開発のフレームワークです。
「どじゃんご」でも「でぃーじゃんご」でもなく、「ジャンゴ」と読みます。
名前の由来はギタリストのジャンゴ・ラインハルト氏からだそうです。(Wikipediaより)

そもそも、Webアプリを作るに当たり、(フレームワークに頼らずにJavaScriptやPHPなど言語もともとの機能だけを用いて作ろうとした方はわかると思いますが) 簡単な機能を実装するだけでも、セッション管理やデータベースへの接続など、面倒な作業がくっついてきます。

Djangoフレームワークは、

  • セキュリティ
  • 保守性
  • テンプレート

など、Web開発で誰しも直面することの多い共通の問題を、出来合いの部品をいっぺんに提供することで解決し、実際の中身の開発のほうに集中させてくれるものだな、という認識で大丈夫かなと思います。

なぜDjango?

サーバサイドのWebフレームワークとしては、Rails, Laravel, Node.jsなど有名なものが他にもあり、同様のWebアプリを実現することができます。 ここでDjangoをあえて選択する動機として、

PythonでWeb開発できる

というメリットがあると考えています。

Pythonはコードを簡潔に、きれいにかける言語として機械学習や画像処理の分野でも人気を高めています。

デジコアに開発の誰もやったことないDjangoを採用したねらいとしても、 今後数年利用者が多いと思われるPython言語を用いることで、開発、運用に関われる人が増えるのではというものがあります。

デメリットを挙げるとすれば、日本語のドキュメントが比較的少ないので、英語が読めないと少し面倒だということ(Python, プログラミング全般そうですが)があります。

また、パフォーマンスについては今のところあまり考慮していないですが、厳格な運用を求められるWebアプリの場合はもっと良い選択肢があると思います。

MVCアーキテクチャ

もう一つDjangoを利用することによる大きな利点として、
他のWebフレームワーク同様、MVCアーキテクチャの恩恵にあずかれるというものがあります。

このアーキテクチャに従うことで、Webアプリの処理と表示部分が分かれ、見通しが良く、保守性が高くなると考えられます。

MVCが実際何なのかについては調べたり、アプリを開発していく中でわかっていくものだと思うので、
ここでは、MVCが何でどう対応するか確認するため、今見ているこのページがどのように組み立てられているか、実際のコードと一緒に見ていこうと思います。

Model

データベースのスキーマ(構造)を記述します。
それぞのクラスは実際のデータベースのテーブルと対応しています。

class Article(models.Model):
    member = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = MDTextField('Contents', blank=True)
    article_image = models.ImageField(upload_to='article_image/', default='null')
    article_tags = models.ManyToManyField(ArticleTag,blank=True)
    relates_works=models.ManyToManyField(Work,blank=True)
    pub_date = models.DateTimeField(blank=True,null=True)
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ('-pub_date',) # 新着順にする

    def __str__(self):
        return self.title

    def formatted_markdown(self):
        return markdownify(self.content) # モデルデータをMarkDown形式に変換してくれる

これは、/blog/models.pyに記述されたArticleクラスです。

このようにクラス定義をすることで、実際のデータベースにもそれぞれのフィールドをカラムとして持ったArticleテーブルが生成できるほか、 データベースへのアクセスもこのクラスを通して行えるようになるので、生のSQL文を打たずに済むという利点があります。

Controller

指定のURLにアクセスがあったときの実際のサーバの処理を記述します。
ちなみに、Djangoではviews.pyというファイル名なので、少しだけまぎらわしいです。

def show(request,id=1):
    article = Article.objects.filter(id=id).first()
    if article.is_active == False and article.member != request.user:
        return redirect(to='/blog')
    params = {
        'article':article,
        'is_edit_user':request.user == article.member,
        'is_login_user':request.user.is_authenticated,
    }
    return render(request,'blog/show.htm',params)

これは、/blog/views.pyに記述されたshow関数です。

このページにアクセスした時に行われる処理ですが、Pythonらしく、比較的短めに記述されていることがわかるのではないでしょうか。

主な処理としては、URLで指定されたidの記事のデータをデータベースから取得し、articleというパラメーターとして後述のViewに埋め込んで表示を返す、ということをやっています。

View

実際の画面表示を担当する部分です。
ページのレイアウト、デザインなどをここで調整します。

<div class="container">
    <div class="row">
        <div class="col-md-12">
            <div class="shadow p-3 mb-3">
                <a href="/blog" class="btn btn-primary">一覧へ</a>
                <a href="/blog/article/{{article.id}}/tags" class="btn btn-primary">Tag</a>
                {% if is_edit_user %}
                <a href="/blog/article/{{article.id}}/edit" class="btn btn-primary">編集</a>
                {% endif %}
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            {% if article.article_image.url == 'null' %}
            <img src="{{article.article_image.url}}" alt="">
            {% endif %}
            <div class="inline-block">
                <div style="float: right;">
                    <img src="{{article.member.icon.url}}" alt="" style="height:50px; border-radius: 50%;">
                    <a style="font-size:20px;margin-top:5px;"
                        href="/member/{{article.member.profile.id}}">{{article.member.username}}</a>
                </div>
                <div class="text-center">
                    <h2 style="border-bottom: solid 2px #87CEFA;">
                        {{article.title}}
                        {% if article.is_active == False %}
                        (非公開)
                        {% endif %}
                    </h2>
                </div>
            </div>
            {% for article_tag in article.article_tags.all %}
            <a href="/blog/tag/{{article_tag.id}}" class="badge badge-pill badge-primary">{{article_tag.name}}</a>
            {% endfor %}
        </div>
    </div>
    <div class="row">
        <div class="col-12">
            <div id="content">{{ article.content|markdown|safe }}</div>
        </div>
    </div>
</div>

これは、/blog/templates/blog/show.htmに記述されたHTMLファイルの記事表示部分を抜粋したものです。

普通のHTMLと少し違うのは、{{}}で埋め込む変数の場所を指定したり、if文やfor文などを利用して動的なページ生成が実現できるということでしょうか。

26行目の{{article.title}}や40行目の{{article.content}}など、先程のControllerでパラメータに指定したarticleを用いて、データを埋め込む場所を指定している、ということが確認できると思います。


最後に

少々長くなりましたが、ここらでDjangoについての説明を終わらせていただきます。

Pythonで処理を簡潔に書けるため、Djangoはとっつきやすく、わかりやすいと思っています(※個人の意見)

デジコアはみんなでずっと使うことになりそうなアプリなので、開発に携わる人が増えて、改善がますます活発になっていったらと思います。