【Django】WebAPIから取得してきたデータをDBに保存する



大分久しぶりに投稿します。
前回はこちら

https://qiita.com/ri-tama/items/cf912a9795f176556bcf



今回は表題通り

## マイリストへ映画を登録します

TMDbのAPIを使い映画を検索したあと
データベースへ保存します。

保存するデータは
・MyModel
title,number(TMDb内での映画ID),image(ポスターイメージ),tags,user

・Tag
name

この2つです。

```python models.py

class Tag(models.Model):
    name = models.CharField(max_length=100,blank=True,null=True)
    def __str__(self):
        return str(self.name)




class MyModel(models.Model):
    title = models.CharField(max_length=100)
    number = models.IntegerField(blank=True,null=True)
    image = models.ImageField(upload_to='images/',blank=True,null=True)
    user = models.ForeignKey('auth.User',on_delete=models.CASCADE,blank=True,null=True)
    tags = models.ManyToManyField(Tag,blank=True,null=True)


    def __str__(self):
        return str(self.title)

```
1つのアクションで2つのデータベースに保存します。




フローチャート図です。黄色で囲った箇所が該当箇所になります。
![スクリーンショット 2023-03-22 235159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/08070f7c-1707-c74b-717a-bdb049c49e6a.png)



順を追って説明していきます。
今回使うのはdjangoのCreateViewです。
MyCreateViewというクラスを定義しています。



```python views.py

class MyCreateView(LoginRequiredMixin,CreateView):
#登録のview(タイトル、ナンバー、画像を取得)
    def post(self, request, *args, **kwargs):
        title = request.POST.get('title')
        number = request.POST.get('number')
        image = request.POST.get('image')
        user = request.user
        tag = request.POST.get('tags')
```

取得してきたデータを篩にかけます。
もしMyModelというデータベースにnumberが存在していたら
TOPページに戻すようにしています。
要するに一度登録してあるものは、もう登録できないよ。ということです。

### ここで1つ引っかかったポイントがあります。
ユーザー機能を後から実装したので
同じ映画を別のユーザーで登録した時にTOPぺージに戻されてしまう事態になりました。
### もうタイトル登録してあるじゃん、ってdjangoから叱られたわけです。

djangoにとってはAさんもBさんも同じ人間ですからね。
ですのuser=userと付け加えて
同じ映画を他のユーザーが登録した時に、Aさんは登録してあるけどまだBさんは登録してないね？じゃあここは通っていいよ、ということで丸く収まりました。

```python  
        if MyModel.objects.filter(number=number,user=user).exists():
            #number=numberでタイトル識別、user=userでユーザー識別。どちらも存在していた場合indexへ戻す
            return redirect('index')
```

　　
次は登録の部分です。
MyModelにデータを保存します。

tagについてはtags = tag.split(",")、タグをカンマで区切れるようにしています。複数のタグを登録する時のものです。
for文でtagsをtに代入していき、name=tでTagのデータベースにTagを保存し
my_modelにTagを付け加えていきます。
Tagは使いまわしすることを想定し、またタグを絞ってデータを抽出することもあるので、
Tagというデータベースへ保存してあります。


登録したメッセージをテンプレートに渡し、リストへ移動します。


```python
        else:
            my_model = MyModel.objects.create(title=title,number=number,image=image,user=user)
            tags = tag.split(",")
            for t in tags:
                tag_obj=Tag.objects.get_or_create(name=t)
                my_model.tags.add(tag_obj)          
            messages.success(self.request,'登録しました。')
            return redirect('list')
```

テンプレートは
以下の通りです。

```HAML
<h3>{{ cinema_data.title }}</h3>
<form method="POST" action="{% url 'create' %}">
  {% csrf_token %}
    <input type="hidden" name="title" value="{{ cinema_data.title }}">    
    <input type="hidden" name="number" value="{{ cinema_data.id }}">
    <input type="hidden" name="image" value="{{ cinema_data.image }}">
    <input type="hidden" name="user" value="{{ request.user.id }}">
    <button type="submit" class="btn btn-primary">登録する</button>
</form>           

```
登録するボタンを押せばデータをとってきて登録完了となります。

## 最後に
ということで
データを保存することができました。

機能実装については、後からやると想定しないことが起きやすいので
先に定義する方が好ましいと思います。

拙いコードで恐縮ですが何かあればコメントください。


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