[Django]DetailViewを使わずに詳細画面を作成する方法

先日、Webアプリケーションを作製していたところ、詳細画面に別モデルの登録機能をつけたい.....となったときにDetailViewで詳細画面を作成していたため、登録機能をつけるのに難航してしまった。

```Python
from django.views.generic import CreateView, TemplateView, ListView, DetailView

class TestDetailView(DetailView):

model = TestModel

def post(self, request, *args, **kwargs):

        form    = Test2Form(request.POST)

        if form.is_valid():
            print("バリデーションOK")
            form.save()
        else:
            print("バリデーションNG")
            print(form.errors)

        return redirect("test:home")
```

```Python
#models.py

class TestModel(models.Model): #詳細表示したいモデル

    deadline_m = models.DateField(verbose_name= '締め切り日',)
    start_m = models.DateField(verbose_name= '開始日',)
    end_m = models.DateField(verbose_name= '終了日',)

    def __str__(self):
        
        return (self.start_m) + (self.end_m)

class Test2Model(models.Model): #登録したいモデル

    省略  

```

```Python
#froms.py

class Test2Form(ModelForm):
    
    class Meta:
        
        model = Test2Model
        
        fields = ['test', 'ooo', 'iii']


```



これで　DetailViewにフォームが表示されて登録できるぞ.....

と思っていたらフォームが表示されない。


ということでCreateViewで作れないかと検討した。


### 解決策

結果からいうと、 CreateView　で　def get_context_data　を使い、自身のpkを取得して、データベースからpkのレコードを検索させて保存しておくという方法である。


### 修正前

```Python
#views.py
class DetailAndPostView(DetailView):
    
    template_name = 'test/DandP.html'
    
    model = TestModel
    
    context_object_name = 'MI'
    
    def post(self, request, *args, **kwargs):

        form    = Test2(request.POST)

        if form.is_valid():
            print("バリデーションOK")
            form.save()
        else:
            print("バリデーションNG")
            print(form.errors)

        return redirect("リダイレクト先")


```
```html
html
<div class="p3">
   <a>締切日</a><br>
   <a>{{ MI.deadline_m }}</a>
</div>
<div class="p4">
   <a>開始日</a>
   <a>{{ MI.start_m }}</a>
</div>
<div class="p4">
   <a>終了日</a>
   <a>{{ MI.end_m }}</a>
 </div>


```

### 修正後

```Python

class DetailAndPost(CreateView):
    
    template_name = 'account/DandP.html'
    
    form_class = Test2Form
    
    def get_context_data(self, **kwargs):
        
        context = super().get_context_data(**kwargs)　#恒例のもうおまじないみたいなやつ
        
        
        Xcode = self.kwargs['pk'] #ここで自身のpkを変数に保存しておく
        
        
        start = TestModel.objects.get(code_m=Xcode).start_m #pk で　データベースから検索させヒットしたものを変数に保存
        
        end = TestModel.objects.get(code_m=Xcode).end_m　#上に同じ

        deadline = TestModel.objects.get(code_m=Xcode).deadline_m　#上に同じ
        
        context.update({                              #context.update　で名前をつけ、変数に保存されているデータをhtml上で使えるようにする。

                'start': start,
                'end': end,
                'deadline': deadline
                })
        
        return context #値を返す


```


```html
html
<div class="p3">
   <a>締切日</a><br>
   <a>{{ deadline }}</a>
</div>
<div class="p4">
   <a>開始日</a>
   <a>{{ start }}</a>
</div>
<div class="p4">
   <a>終了日</a>
   <a>{{ end }}</a>
 </div>
```

これでうまくいきました！

### 解説

DetailView　では　オブジェクト名を指定してあるpkの値のレコードを参照できたが、　CreateViewにはその機能はないので

def get_context_data 内で　自身のpk を取得し、　データベースで検索させて　データをある名前で保存し、使えるようにするといったものである。


### 感想

 Djangoを使って思いましたが、いろいろと不便なことが多い気がする。　かゆいところにまったく手が届かないので、かゆいところがでてきた場合には毎度毎度、孫の手を作ってかゆいところの解消をしている気がする。

Django初心者だからそう感じるんですかねぇ...　Django歴長いひとの感想待ってます。