diadia

興味があることをやってみる。自分のメモを残しておきます。

Django:ModelChoiceFieldを使う

ドキュメント:https://docs.djangoproject.com/ja/2.2/ref/forms/fields/#modelchoicefield

現在困っているのは、Formにdjango.contrib.auth.models.Userオブジェクトを渡してフォームから別のオブジェクトを生成しようと試みているが、form.is_valid()でうまく行かない。この状況でmodelchoicefieldなる存在を知った。これが解決の糸口になるかもしれないので少々調べてみることとする。

https://www.subthread.co.jp/blog/20160531/
こちらの記事によるとやはりオブジェクトをそのまま利用するために使われるようだ。

使い方を調べる

基本的にforms.Formでmodelchoicefieldを使う記事が多い。しかしながらforms.ModelFormでも使用することができるようだ。それは以下の記事を参照
https://natsumesouxx.hatenadiary.org/entry/20100523/1274565168

from django.forms.models import ModelChoiceField

class CustomChoiceField(forms.ModelChoiceField):

class BlogForm(ModelForm):
    
    user_obj = CustomChoiceField(queryset=User.objects.all())
    class Meta:
        model = Contact    

ModelChoiceFieldを動的に使う場合の注意点

ModelChoiceFieldを動的に使う場合には、forms.pyにおけるModelFormのクラス定義に注意しなければならない。
動的に使うとは、views.pyでformインスタンスを生成し、views内で呼び出したquerysetをformインスタンスにあてがい動的な仕様に変更する。

views.py
from django.shortcuts import render 
from django.views.generic import View
from products.forms import TestModelForm


class TestView(View):
    def get(self, request, *args, **kwargs):
        context = {}
        form = TestModelForm()
        form.fields['name'] = Products.objects.filter(price=100)
        context["form"] = form
        
        return render(request, "test_model/test_modelchoice.html"

しかしながらforms.pyを以下のようにnoneを使ってしまうと、views.pyでエラーが出てしまう。理由はよくわからない。

forms.py
form django import forms
from django.forms.models import ModelChoiceField
from products.models import Product

class TestModelForm(forms.ModelForm):
    name = ModelChoiceField(queryset=Products.objects.none())
    
    class Meta:
        model  = Product
        fields = ("name", "category", "price")

必ずall()を使うこと。

forms.py
form django import forms
from django.forms.models import ModelChoiceField
from products.models import Product

class TestModelForm(forms.ModelForm):
    name = ModelChoiceField(queryset=Products.objects.all())
    
    class Meta:
        model  = Product
        fields = ("name", "category", "price")