program story

Django : 양식을 사용하여 하나의 템플릿에 여러 모델

inputbox 2020. 8. 4. 07:20
반응형

Django : 양식을 사용하여 하나의 템플릿에 여러 모델


지원 티켓 추적 앱을 만들고 있는데 한 페이지에서 만들고 싶은 몇 가지 모델이 있습니다. 티켓은 ForeignKey를 통해 고객의 것입니다. 메모는 ForeignKey를 통한 티켓에도 속합니다. 고객 (전체 프로젝트)을 선택하거나 새로운 고객을 생성 한 다음 티켓을 생성하고 마지막으로 새로운 티켓에 할당 된 메모를 생성하는 옵션을 갖고 싶습니다.

Django를 처음 사용하기 때문에 매번 새로운 기능을 시도하면서 반복적으로 작업하는 경향이 있습니다. ModelForms를 가지고 놀았지만 일부 필드를 숨기고 복잡한 유효성 검사를 수행하고 싶습니다. 내가 찾고있는 제어 수준은 양식 세트가 필요하거나 손으로 모든 작업을 수행하는 지루하고 수동으로 코딩 된 템플릿 페이지로 완성되는 것처럼 보입니다.

내가 놓친 멋진 기능이 있습니까? 양식 집합 사용에 대한 좋은 참조 또는 예가 있습니까? 나는 그들을 위해 API 문서에 주말 내내 보냈다. 나는 여전히 실마리가 없다. 모든 것을 분류하고 손으로 코딩하면 디자인 문제입니까?


이것은 ModelForms 로 구현하기가 너무 어렵지 않습니다 . 양식 A, B 및 C가 있다고 가정하겠습니다. 각 양식과 페이지를 인쇄하면 이제 POST를 처리해야합니다.

if request.POST():
    a_valid = formA.is_valid()
    b_valid = formB.is_valid()
    c_valid = formC.is_valid()
    # we do this since 'and' short circuits and we want to check to whole page for form errors
    if a_valid and b_valid and c_valid:
        a = formA.save()
        b = formB.save(commit=False)
        c = formC.save(commit=False)
        b.foreignkeytoA = a
        b.save()
        c.foreignkeytoB = b
        c.save()

다음 은 사용자 지정 유효성 검사를위한 문서입니다.


나는 단지 하루 전에 같은 상황에 있었고, 여기 내 2 센트가 있습니다.

1) 여러 모델 항목에 대한 가장 짧고 간결한 데모는 단일 형식으로 여기에서 발견되었습니다 . .

간단히 말해서 : 각 모델에 대한 양식을 작성하고 keyarg를 <form>사용하여 하나의 템플리트에 둘 다 제출하고 prefix보기가 유효성 검증을 처리하도록하십시오. 종속성이있는 경우 종속 항목보다 먼저 "상위"모델을 저장하고 "자식"모델의 저장을 커밋하기 전에 외래 키에 대해 상위 ID를 사용하십시오. 링크에는 데모가 있습니다.

2) 어쩌면 폼 세트 가이 작업을 수행 할 수는 있지만, 필자가 자세히 설명하는 한 폼 세트는 기본적으로 동일한 모델의 배수를 입력하기위한 것이며 외래 키로 다른 모델 / 모델에 선택적으로 연결 될 수 있습니다. 그러나 둘 이상의 모델 데이터를 입력 할 수있는 기본 옵션이없는 것 같으며 이는 폼셋이 의도 한 것이 아닙니다.


나는 최근에 약간의 문제가 있었고 이것을하는 방법을 알아 냈습니다. 기본, B, C의 세 클래스가 있고 B, C에 기본에 대한 외래 키가 있다고 가정합니다.

    class PrimaryForm(ModelForm):
        class Meta:
            model = Primary

    class BForm(ModelForm):
        class Meta:
            model = B
            exclude = ('primary',)

    class CForm(ModelForm):
         class Meta:
            model = C
            exclude = ('primary',)

    def generateView(request):
        if request.method == 'POST': # If the form has been submitted...
            primary_form = PrimaryForm(request.POST, prefix = "primary")
            b_form = BForm(request.POST, prefix = "b")
            c_form = CForm(request.POST, prefix = "c")
            if primary_form.is_valid() and b_form.is_valid() and c_form.is_valid(): # All validation rules pass
                    print "all validation passed"
                    primary = primary_form.save()
                    b_form.cleaned_data["primary"] = primary
                    b = b_form.save()
                    c_form.cleaned_data["primary"] = primary
                    c = c_form.save()
                    return HttpResponseRedirect("/viewer/%s/" % (primary.name))
            else:
                    print "failed"

        else:
            primary_form = PrimaryForm(prefix = "primary")
            b_form = BForm(prefix = "b")
            c_form = Form(prefix = "c")
     return render_to_response('multi_model.html', {
     'primary_form': primary_form,
     'b_form': b_form,
     'c_form': c_form,
      })

이 방법을 사용하면 동일한 페이지에서 세 가지 개체를 모두 생성 할뿐만 아니라 필요한 모든 유효성 검사를 수행 할 수 있습니다. 또한 동일한 페이지에서 여러 B, C 객체를 생성 할 수 있도록 자바 스크립트와 숨겨진 필드를 사용했습니다.


MultiModelForm 에서이 django-betterforms설명되어 일을 할 수있는 편리한 래퍼입니다 Gnudiff의 대답 . ModelForm단일 폼으로 투명하게 사용되는 (적어도 기본 사용법의 경우) 단일 클래스에서 일반을 래핑 합니다. 아래 문서에서 예제를 복사했습니다.

# forms.py
from django import forms
from django.contrib.auth import get_user_model
from betterforms.multiform import MultiModelForm
from .models import UserProfile

User = get_user_model()

class UserEditForm(forms.ModelForm):
    class Meta:
        fields = ('email',)

class UserProfileForm(forms.ModelForm):
    class Meta:
        fields = ('favorite_color',)

class UserEditMultiForm(MultiModelForm):
    form_classes = {
        'user': UserEditForm,
        'profile': UserProfileForm,
    }

# views.py
from django.views.generic import UpdateView
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.contrib.auth import get_user_model
from .forms import UserEditMultiForm

User = get_user_model()

class UserSignupView(UpdateView):
    model = User
    form_class = UserEditMultiForm
    success_url = reverse_lazy('home')

    def get_form_kwargs(self):
        kwargs = super(UserSignupView, self).get_form_kwargs()
        kwargs.update(instance={
            'user': self.object,
            'profile': self.object.profile,
        })
        return kwargs

I currently have a workaround functional (it passes my unit tests). It is a good solution to my opinion when you only want to add a limited number of fields from other models.

Am I missing something here ?

class UserProfileForm(ModelForm):
    def __init__(self, instance=None, *args, **kwargs):
        # Add these fields from the user object
        _fields = ('first_name', 'last_name', 'email',)
        # Retrieve initial (current) data from the user object
        _initial = model_to_dict(instance.user, _fields) if instance is not None else {}
        # Pass the initial data to the base
        super(UserProfileForm, self).__init__(initial=_initial, instance=instance, *args, **kwargs)
        # Retrieve the fields from the user model and update the fields with it
        self.fields.update(fields_for_model(User, _fields))

    class Meta:
        model = UserProfile
        exclude = ('user',)

    def save(self, *args, **kwargs):
        u = self.instance.user
        u.first_name = self.cleaned_data['first_name']
        u.last_name = self.cleaned_data['last_name']
        u.email = self.cleaned_data['email']
        u.save()
        profile = super(UserProfileForm, self).save(*args,**kwargs)
        return profile

"I want to hide some of the fields and do some complex validation."

I start with the built-in admin interface.

  1. Build the ModelForm to show the desired fields.

  2. Extend the Form with the validation rules within the form. Usually this is a clean method.

    Be sure this part works reasonably well.

Once this is done, you can move away from the built-in admin interface.

Then you can fool around with multiple, partially related forms on a single web page. This is a bunch of template stuff to present all the forms on a single page.

Then you have to write the view function to read and validated the various form things and do the various object saves().

"Is it a design issue if I break down and hand-code everything?" No, it's just a lot of time for not much benefit.


According to Django documentation, inline formsets are for this purpose: "Inline formsets is a small abstraction layer on top of model formsets. These simplify the case of working with related objects via a foreign key".

See https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets

참고URL : https://stackoverflow.com/questions/569468/django-multiple-models-in-one-template-using-forms

반응형