解説記事の構成
No. | タイトル | |
---|---|---|
1 | PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(1)【環境構築編】 | |
2 | [PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(2)【プロジェクト作成編】] (http://qiita.com/carat_yoshizaki/items/926f702198bdfe8c6bd2) | |
3 | [PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(3)【アプリケーション作成・DB設定編】] (http://qiita.com/carat_yoshizaki/items/c9a5299b77b99ff07e4a) | |
4 | PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(4)【ルーティング設定・MTVデザインパターン入門編】 | |
5 | PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(5)【Django shellでDB操作入門編】 | ← |
6 | PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(6)【MTVデザインパターン完成編】 |
開発環境
- OS: Mac OS Sierra (10.12)
- Python 3.5.2
Macの環境を前提として話を進めていきます。
Pythonのバージョン確認は以下の通りです。
$ python3 --version
Python 3.5.2
Django shell
今回は Django shell
の使い方を紹介します。
前回は、Django adminを使って、DBを操作したり確認したりする方法を紹介しました。
Ruby on Railsに慣れている方は、そんなのコンソールの rails c
で操作したり確認したりすれば良いんじゃないの?と思われる方もいらっしゃると思いますが、その通りかと思います。
Djangoもそういったコンソールを備えており、それが Django shell
というわけです。
Django shellを使ってみよう
まず、Django shell
を立ち上げます。
$ python3 manage.py shell
Python 3.5.2 (default, Jun 29 2016, 13:43:58)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
Django shellでデータを表示させよう
では、早速定義したモデルである Post
のデータを見てみましょう。
>>> Post.objects.all()
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'Post' is not defined
残念ながらエラーが出てしまいました(Ruby on Rails同様の手順でならエラーは出ないのに)。
Djangoでは、最初にモデルをインポートしないといけないようです。
>>> from blog.models import Post
>>> Post.objects.all()
<QuerySet [<Post: サンプル記事のタイトル>]>
これでDB内のデータを確認することが出来増しtあ。
QuerySet
という名前が出てきていますが、クエリセットとはモデルが提供しているオブジェクトのリストのことだそうです。
Coffee Break:DjangoとRuby on Railsを比べてみる
これまでの記事を読まれている方はお気づきかも知れませんが、私は Ruby on Rails を一番最初のWebフレームワークとして学習し、それが自分の中のスタンダードになっているため、Djangoはところどころで、Ruby on Railsに比べると使いにくいなという印象を受けています。
しかし、機械学習を使用するためには、PythonのWebフレームワークは非常に魅力的です。
個人的には、Ruby on RailsでWebアプリケーションの土台を作り、DjangoでWeb APIを作るのがオススメです。
Django shellでobjectを作ろう
データベースに新しい Post
を作成します。
>>> Post.objects.create(author=ryosuke, title="ryosuke's article", text="これはQiita用の記事です")
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'ryosuke' is not defined
エラーが出ましたね。
author=ryosuke
でエラーが起きました。
author
って指定した名前で勝手に増えるものではないのですね。。。
このあたりは、実は Django でモデルを作った際(PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(3):モデルの作成)に、 blog/models.py
内で
author = models.ForeignKey('auth.User')
として、Userモデルを参照するように設定しているためです。
ここを単純に文字列として定義しておけば、新規の名前に対しても問題なくオブジェクトを作成できるというわけです。
しかし、これではユーザーの名前の管理が難しくなるので、ユーザーはユーザー、ポストはポストとして管理して、ポストからユーザーを参照するようにしています。
今回は新しくユーザーを作ることはせず、ryosuke
というユーザーに admin
の情報を与え、そこから新規オブジェクトを作成していきます。
>>> from django.contrib.auth.models import User
>>> User.objects.all()
<QuerySet [<User: admin>]>
>>> ryosuke = User.objects.get(username='admin')
>>> ryosuke
<User: admin>
>>> Post.objects.create(author=ryosuke, title="ryosuke's article", text="これはQiita用の記事です")
<Post: ryosuke's article>
これで上手くいきました。
Postのオブジェクトリストを見てみましょう。
>>> Post.objects.all()
<QuerySet [<Post: サンプル記事のタイトル>, <Post: ryosuke's article>]>
新しいPost
が増えていることが分かると思います。
Django shellで特定条件のオブジェクトを抽出しよう
特定条件を抽出する場合は all()
であった部分を filter()
を使い、引数にプロパティの情報を与えます。
例えば、author=ryosuke
のPostのみ抽出する場合は以下のようになります。
>>> Post.objects.filter(author=ryosuke)
<QuerySet [<Post: サンプル記事のタイトル>, <Post: ryosuke's article>]>
今の所、全てのオブジェクトと変わりがありませんが、author
が増えてきた場合は、このようにして、著者ごとにわけることができます。
完全に一致する条件の抽出だけでなく、一部に特定の文字列を含むような部分一致の検索もできます。
>>> Post.objects.filter(title__contains='article')
<QuerySet [<Post: ryosuke's article>]>
title
に __contains
を付け加えることで、部分一致も上手く扱えるようになります(これ結構便利です)。
Pythonでは、上記の用にアンダーバーが2つ続くことがよくあります。
参考:Django Girls Tutorial:クエリセット1
Note
title と contains の間に、アンダーバーが2個続いていますが、これはDjangoのORMの構文です。フィールド名のtitleと、照合タイプのcontainsを、2つのアンダーバーで連結させています。もしアンダーバーが1個だけだと、title_contains というフィールド名だと判断されてしまい、エラーになります。("FieldError: Cannot resolve keyword title_contains")
つぎに、これもよく使う機能ですが、既に公開済みの記事のみを抽出する方法です。
Qiitaでも記事の作成はしますが、下書きで一旦置いておく場合ありますよね。
この現時刻で、公開済みのみを抽出したい場合の方法です。
>>> from django.utils import timezone
>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet [<Post: サンプル記事のタイトル>]>
勘の鋭い方ならお分かりかもしれませんが、lte
の部分が contain
同様、フィルターを書ける際の条件分になっています。
lte
は less than or equal to
の略で、数学的な記号では 「published_date <= 現時刻」ということになります。
現時刻より前もしくは現時刻と一致した場合は抽出するといった条件分ですね。
先ほどDjango shellから追加したオブジェクトは published_date
を設定していなかったので、今回の条件には該当せずとなっています。
変数名にはひとつのアンダーバーを使うことが多い為、DjangoのORMの構文にはアンダーバー二つ続きを採用しています。アンダーバーが一つだと変数名として扱われてしまうため"FieldError: Cannot resolve keyword title_contains"
エラーとなります。
オブジェクトの内容を更新
さきほど作成したオブジェクトがまだ公開 (publish
) されていなかったので、これを公開していきましょう。
post = Post.objects.get(id=2)
>>> post
<Post: ryosuke's article>
blog/models.py
で publish()
メソッドを以下のように定義しているため、このメソッドを使えば、簡単に published_date
の値を更新することができます。
def publish(self):
self.published_date = timezone.now()
self.save()
では、このpublish()
メソッドを使っていきます。
>>> post.publish()
>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet [<Post: サンプル記事のタイトル>, <Post: ryosuke's article>]>
これで、無事記事を公開することが出来ました。
オブジェクトのリストの並べ替え
最後に簡単に並べかえの使い方を知っておきましょう。
Webページでは、金額や日時による並べ替えをすることが多々有り、よく使うコマンドになると思います。
並べ替えには order_by()
を使用します。
>>> Post.objects.order_by('created_date')
<QuerySet [<Post: サンプル記事のタイトル>, <Post: ryosuke's article>]>
基本的には、日時であれば古い順に並びます。
新しく追加した順に並び替えたい場合は、この逆順を以下のように指定すればできます。
>>> Post.objects.order_by('-created_date')
<QuerySet [<Post: ryosuke's article>, <Post: サンプル記事のタイトル>]>
なんと、order_by
の引数に -
を付けるという発想。
asc
や desc
ではないのですね(たぶんこの辺りもサポートしてると思いますが)。
これで並べ替えも出来るようになりました。
Django shellの終了
コンソールを立ち上げたものの、最初は終了の仕方がよく分からないといったことがあります。
>>> exit()
この最後の ()
もお忘れ無く。
次回の解説記事
PythonのWebアプリケーション(Django)を初心者にもわかりやすく解説(6)【MTVデザインパターン完成編】
参考文献
おまけ
フォローお待ちしています!
- Qiita: Carat 吉崎
- twitter:@carat_yoshizaki
- はてなブログ:Carat COOのブログ
- ホームページ:Carat
サービス紹介
「数学→プログラミング→Webアプリケーション」まで一気に学べる機械学習のマンツーマン家庭教師サービス「キカガク」に興味のある方はお気軽にご連絡ください。