LoginSignup
0
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-11-10

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

0
1
0

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
  3. You can use dark theme
What you can do with signing up
0
1