Dockerで始めるDjango生活(5日目)

### 初めに
5日目です。
4日目は[こちら](https://qiita.com/ghayato/private/098dfe5573745f40e45c)
前回は管理サイトを作成して、管理サイトから投稿しました。
今回はシェルから投稿しようと思います。
### 目次
1. pythonシェルを開く
2. シェルから投稿する

## 1. pythonシェルを開く
まずは、myprojectディレクトリに移動します。

```
# cd /root/projects/myproject/myproject
# pwd
/root/projects/myproject/myproject
# ls
blog  db.sqlite3  manage.py  myproject
#
```
それではpythonシェルを開こうと思います。

```
# python3 manage.py shell
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 1+2
3
>>> 2*2
4
>>>
```
上の様に

```
>>>
```
が表示されれば大丈夫です！

## 2. シェルから投稿する
では、実際に投稿しようと思います。

```
>>> from django.contrib.auth.models import User
>>> from blog.models import Post
>>> user = User.objects.get(username='admin')
>>> post = Post(title='Another post',
... slug='another-post',
... body='Post body.',
... author=user)
>>> post.save()
>>>
```
すると、管理画面を確認すると下の様にAnother Postが追加されています。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895676/bfc2c402-0d38-0e74-ede3-6521b808253f.png)
この方法では、一度メモリにオブジェクトを作成してからデータベースに保存する方法です。
次の方法で実行すると一度のコマンドでオブジェクトを作成してデータベースに保存します。

```
>>> Post.objects.create(title='one more post',
... slug='one-more-post',
... body='Post body.',
... author=user)
<Post: one more post>
>>>
```
画面を確認すると新たにone more postが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895676/9b28bf88-438d-1a82-338c-77969bbda494.png)

次にタイトルを更新してみます。

```
>>> post.title = 'New title'
>>> post.save()
>>>
```
再度画面を確認するとAnother postのタイトルがNew titleになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895676/9e751735-155f-af22-737d-a99fa20a3167.png)

## 3. 投稿内容を取得する
全件取得する

```
>>> all_posts = Post.objects.all()
>>> all_posts
<QuerySet [<Post: one more post>, <Post: New title>, <Post: テスト>]>
>>>
```
フィルターをかけて取得する

```
>>> Post.objects.filter(publish__year=2020)                           # publishの年が2020のもの
<QuerySet [<Post: one more post>, <Post: New title>, <Post: テスト>]>
>>> Post.objects.filter(publish__year=2020, author__username='admin') #年が2020かつ投稿者がadminのもの
<QuerySet [<Post: one more post>, <Post: New title>, <Post: テスト>]>
>>> Post.objects.filter(publish__year=2020) \
... .exclude(title__startswith='one')                                 #年が2020かつタイトルがoneから始まらないもの
<QuerySet [<Post: New title>, <Post: テスト>]>
>>> Post.objects.order_by('title')                                    #タイトル順(昇順)
<QuerySet [<Post: New title>, <Post: one more post>, <Post: テスト>]>
>>> Post.objects.order_by('-title')                                   #タイトル順(降順)
<QuerySet [<Post: テスト>, <Post: one more post>, <Post: New title>]>
>>>
```
オブジェクトを削除する

```
>>> post = Post.objects.get(id=1)
>>> post
<Post: テスト>
>>> post.delete()
(1, {'blog.Post': 1})
>>>
```
再度画面を確認するとテストの投稿が削除されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895676/4fe7657d-878f-22b0-9931-9938d2bd1816.png)

blogディレクトリのmodels.pyに下の修正を追記してstatusがdraftのオブジェクトを取得しないようにするオプションを作成する。

``` models.py
class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager,
                     self).get_queryset()\
                          .filter(status='published')
class Post(models.Model):
    ...
    objects = models.Manager()
    published = PublishedManager()
```

## 4. 最後に
この記事では下記の本を参考に書かせていただいています。
この記事ではDjangoを実際に触って動かすことをメインに書いていますので上記のマイグレーションの詳しい説明などはこの本を読んでただければと思います。
[Django 3 By Example - Third Edition](https://www.packtpub.com/product/django-3-by-example-third-edition/9781838981952)