Djangoでダミーの画像データを生成して投稿する

#はじめに

私はDjangoをUdemyから勉強、遊びで触っている程度なので、UdemyのDjango講座のTODOアプリと社内SNSを自分なりに改良しているところなのでレベル的にはそのあたりと変わらないと思います。
[【徹底的に解説！】Djangoの基礎をマスターして、3つのアプリを作ろう！](https://www.udemy.com/course/django-3app/)

なので実用性など全く度外視で動くものを作るという考えでやっております。
初めての記事で至らぬ点やわかりにくいところも多々あると思いますが生暖かい目で見守ってくださると幸いです。

#やりたいこと
Djangoに画像データを登録する際、いちいちデータを打ち込んで、画像を選択して...とするのが非常に面倒だったため何か良い方法がないかと思い調べていると 

```
$ python manage.py runscript <ファイル名>
```
でpythonファイルが実行できると知り、これを使っていくことにしました。
runscriptについては細かくは省きますが、これによりmanage.pyのあるディレクトリにあるscriptsディレクトリの中の任意のファイルのrunメソッドを実行します。
ここではadd_dummies.pyというファイルを作りましたので<ファイル名>にはadd_dummies.pyが入ることになりますね。

#画像の生成
画像を選ぶのが面倒だったため、以下の記事を参考にして画像を生成することにしました。
[Python + PILでダミー画像をつくる。](https://qiita.com/suto3/items/3885e396d63f83e5cb5b)


実際に私が生成に用いたコードは以下になります。
アレンジしたところといえば、パッとみで画像の判別がつくように画像の色、サイズを乱数で変更しているところぐらいでしょうか。

``` add_dummyies.py
from PIL import Image,ImageDraw, ImageFont
import random
colors = [(255,0,0), (0,255,0), (0,0,255),(0,0,0),(255,255,255)]#赤・緑・青・黒・白の色のリスト

def make_image(N):
    """
    画像ファイルを作成
    返り値はファイルの名前
    """
    screen = (200+random.randint(0,100), 200+random.randint(0,100))
    pen_color=random.choice(colors)
    bg_color=random.choice(colors)
    img = Image.new('RGB', screen, bg_color)
    x, y = img.size
    u = x - 1
    v = y - 1
    draw = ImageDraw.Draw(img)
    draw.line((0, 0, u, 0), pen_color)
    draw.line((0, 0, u, v), pen_color)
    draw.line((0, 0, 0, v), pen_color)
    draw.line((u, 0, 0, v), pen_color)
    draw.line((u, 0, u, v), pen_color)
    draw.line((0, v, u, v), pen_color)
    filename="/sample_{}.jpg".format(N)
    img.save("media"+filename)
    return filename
```

これで任意のn個の画像ファイルを生成し、manage.pyが存在するディレクトリからみて `./media/<画像ファイル>`という場所に画像を保存します。

また、このアプリのモデルは以下のように定義しています。

```models.py
from django.db import models

class RecommendedBook(models.Model):
    author = models.CharField(max_length=100)
    bookTitle = models.CharField(max_length=50)
    content = models.TextField()
    bookImage=models.ImageField(upload_to="")
    genre = models.CharField(max_length=200, null=True, blank=True, default="")
    good = models.IntegerField(null=True, blank=True,default=0)
    goodtext = models.CharField(max_length=500,null=True,blank=True, default="")
    notGood = models.IntegerField(null=True, blank=True,default=0)
    notGoodtext = models.CharField(max_length=500,null=True,blank=True, default="")
```

他の要素もついでに保存したかったのでFaker関数などを用いましたが、そこは今回の主題ではないので省きます。
実行するためにadd_dummies.pyに以下のrunメソッドを追記してやります。
他の要素も追加しなければならないため以下のようになりました。

```add_dummies.py

from book.models import RecommendedBook
import random,string
from faker import Faker
fakegen=Faker("ja_JP")

genres=["技術書","英語","数学","小説","感動","楽しい"]#ジャンルを適当なリストに設定し、あとでランダムに取り出す

fakegen = Faker()

def run():
    N=5#データを５つほど作成
    for entry in range(N):
        imgfile=make_image(entry)
        bookGenre=random.choice(genres)+" "+random.choice(genres)#二つほどジャンルを設定する
        dummy=RecommendedBook(author=fakegen.name(), bookTitle=fakegen.word(),
                              content=fakegen.text(), genre=bookGenre,
                              bookImage=imgfile
                              )
        dummy.save()
```


実行して管理画面を覗くと

![スクリーンショット 2020-05-02 17.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628500/f27dc651-525c-bd61-90ab-869636fc73ca.png)


うまく新しいデータが保存されてました！

#終わり
以上で終わりになります！
~~自分なりには調べてみたのですが良い方法が見つからなかったのでこのような泥臭い方法になってしまいました。~~以下に本記事の上位互換がありましたので紹介させていただきます。
[Django で ダミー画像ファイルを置かずに Python で作成して画像アップロードのテストをする](https://qiita.com/cortyuming/items/051ff633fc56e1e0d409)


また、データを登録するのがforループで回しているためか割と遅いため、ループ数が少なければあまり問題にはなりませんがある程度より多くなってしまうと相当時間がかかってしまうのが大きな問題だと思いました。
「もっと楽にできる方法があるよ！」「こうすれば速くなるよ!」などご教示いただければ嬉しいです
一応本記事のコードがある[githubのページ](https://github.com/N-Eiki/favoritebook)を置いておきます。

最後まで読んでいただきありがとうございました！