[python] 단일 django ModelForm에 여러 모델이 있습니까?
ModelForm
Django 에서 단일 모델에 여러 모델을 포함 할 수 있습니까? 프로필 편집 양식을 만들려고합니다. 따라서 User 모델 과 UserProfile 모델 의 일부 필드를 포함해야합니다 . 현재 나는 이와 같은 두 가지 양식을 사용하고 있습니다.
class UserEditForm(ModelForm):
class Meta:
model = User
fields = ("first_name", "last_name")
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
fields = ("middle_name", "home_phone", "work_phone", "cell_phone")
이를 하나의 양식으로 통합하는 방법이 있습니까? 아니면 양식을 작성하고 db로드 및 저장을 직접 처리해야합니까?
답변
하나의 <form>
html 요소 내의 템플릿에 두 양식을 모두 표시 할 수 있습니다 . 그런 다음보기에서 양식을 별도로 처리하십시오. 여전히 사용할 수 있으며 form.save()
db로드 및 저장을 처리 할 필요가 없습니다.
이 경우에는 필요하지 않지만 동일한 필드 이름을 가진 양식을 사용하려면 prefix
django 양식 에 대한 kwarg를 살펴보십시오 . ( 여기 에 대한 질문에 답했습니다 ).
답변
다음 코드를 사용해 볼 수 있습니다.
class CombinedFormBase(forms.Form):
form_classes = []
def __init__(self, *args, **kwargs):
super(CombinedFormBase, self).__init__(*args, **kwargs)
for f in self.form_classes:
name = f.__name__.lower()
setattr(self, name, f(*args, **kwargs))
form = getattr(self, name)
self.fields.update(form.fields)
self.initial.update(form.initial)
def is_valid(self):
isValid = True
for f in self.form_classes:
name = f.__name__.lower()
form = getattr(self, name)
if not form.is_valid():
isValid = False
# is_valid will trigger clean method
# so it should be called after all other forms is_valid are called
# otherwise clean_data will be empty
if not super(CombinedFormBase, self).is_valid() :
isValid = False
for f in self.form_classes:
name = f.__name__.lower()
form = getattr(self, name)
self.errors.update(form.errors)
return isValid
def clean(self):
cleaned_data = super(CombinedFormBase, self).clean()
for f in self.form_classes:
name = f.__name__.lower()
form = getattr(self, name)
cleaned_data.update(form.cleaned_data)
return cleaned_data
사용 예 :
class ConsumerRegistrationForm(CombinedFormBase):
form_classes = [RegistrationForm, ConsumerProfileForm]
class RegisterView(FormView):
template_name = "register.html"
form_class = ConsumerRegistrationForm
def form_valid(self, form):
# some actions...
return redirect(self.get_success_url())
답변
erikbwork와 저 모두 일반적인 클래스 기반 뷰에 하나의 모델 만 포함 할 수 있다는 문제가있었습니다. 나는 Miao처럼 접근하는 비슷한 방법을 찾았지만 더 모듈화되었습니다.
모든 일반 클래스 기반 뷰를 사용할 수 있도록 Mixin을 작성했습니다. 모델, 필드, 이제 child_model 및 child_field도 정의하십시오. 그러면 Zach가 설명하는 것처럼 두 모델의 필드를 태그로 래핑 할 수 있습니다.
class ChildModelFormMixin:
''' extends ModelFormMixin with the ability to include ChildModelForm '''
child_model = ""
child_fields = ()
child_form_class = None
def get_child_model(self):
return self.child_model
def get_child_fields(self):
return self.child_fields
def get_child_form(self):
if not self.child_form_class:
self.child_form_class = model_forms.modelform_factory(self.get_child_model(), fields=self.get_child_fields())
return self.child_form_class(**self.get_form_kwargs())
def get_context_data(self, **kwargs):
if 'child_form' not in kwargs:
kwargs['child_form'] = self.get_child_form()
return super().get_context_data(**kwargs)
def post(self, request, *args, **kwargs):
form = self.get_form()
child_form = self.get_child_form()
# check if both forms are valid
form_valid = form.is_valid()
child_form_valid = child_form.is_valid()
if form_valid and child_form_valid:
return self.form_valid(form, child_form)
else:
return self.form_invalid(form)
def form_valid(self, form, child_form):
self.object = form.save()
save_child_form = child_form.save(commit=False)
save_child_form.course_key = self.object
save_child_form.save()
return HttpResponseRedirect(self.get_success_url())
사용 예 :
class ConsumerRegistrationUpdateView(UpdateView):
model = Registration
fields = ('firstname', 'lastname',)
child_model = ConsumerProfile
child_fields = ('payment_token', 'cart',)
또는 ModelFormClass 사용 :
class ConsumerRegistrationUpdateView(UpdateView):
model = Registration
fields = ('firstname', 'lastname',)
child_model = ConsumerProfile
child_form_class = ConsumerProfileForm
끝난. 누군가에게 도움이되기를 바랍니다.
답변
인라인 양식 집합을 살펴보아야 할 것 입니다. 인라인 양식 집합은 모델이 외래 키로 관련 될 때 사용됩니다.
답변
여기에서 내 대답을 확인할 수 있습니다.비슷한 문제에 대해 에서 .
등록 및 사용자 프로필을 하나의 양식으로 결합하는 방법에 대해 설명하지만 모든 ModelForm 조합으로 일반화 할 수 있습니다.
답변
나는 django betterforms 의 MultiForm과 MultiModelForm을 사용했습니다. 내 프로젝트에. 하지만 코드는 개선 될 수 있습니다. 예를 들어, 3. +에서 지원하지 않는 django.six에 의존하지만이 모든 것은 쉽게 고칠 수 있습니다.
이 질문은 StackOverflow에 여러 번 나타 났으 므로 이에 대처하는 표준화 된 방법을 찾을 때라고 생각합니다.