search
LoginSignup
1

posted at

updated at

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

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

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")
#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): #登録したいモデル

    省略  

#froms.py

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


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

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

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

解決策

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

修正前

#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
<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>


修正後


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
<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歴長いひとの感想待ってます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1