Nested and Segmented Crispy Layouts

末鹿安然 提交于 2019-12-06 06:59:06

Crispy is independent of this problem. Forms can be included int the template with either:

{{form1}}
{{form2}}
...

or

{% crispy form1 form1.helper %} #although the helper name here is default and not needed
{% crispy form2 %} # form2.helper is implied
...

For the assumptions:

  • I am not calling the correct formfactory
    • form factory is not needed, as there arent multiple versions of any single form
  • I am not properly using formsets
    • also not needed, as there arent multiple versions of any single form
  • I am not referencing the form fields to the correct model fields correctly in the layout of the form helper
    • somewhat true
  • The layout is not possible, or I am applying the wrong code structure to get the result.
    • see below for answer
  • I don't think I can call two forms directly as directly below, as they would not be nested/integrated
    • one can, see below

Code to make an integrated form with related objects/foreign keys:

views.py:

if request.method == 'POST':
  formData = request.POST.dict()
  form1 = form1Form(formData, instance=currentUser, prefix='form1')
  form2 = form2Form(formData, truck=truck, user_cookie=currentUser, prefix='form2')
  form3 = form3Form(formData, truck=truck, instance=truck, user_cookie=currentUser, prefix='form3')
  form4 = form4Form(formData, truck=truck, user_cookie=currentUser, prefix='form4')
  userForm = userFormForm(formData, truck=truck, user_cookie=currentUser, prefix='userForm')
  ... Other forms as needed
if all([form1.is_valid(), form2.is_valid(), form3.is_valid(), form4.is_valid(), userForm.is_valid()]):
  currentUser.save()
  form1.save()
  form2.save()
  ...
# The Get
else:
  form1 = form1Form(instance=truck, prefix='form1')
  form2 = form2Form(instance=truck, prefix='form2')
  form3 = form3Form(instance=truck, prefix='form3')
  form4 = form4Form(instance=truck, prefix='form4')
  userForm = userForm(instance=currentUser, prefix='userForm')

return render(request, 'trucks/weeklyInspection.html', {
  'truck': truck,
  'form1': form1,
  'form2': form2,
  'form3': form3,
  'form4': form4,
  'userForm': userForm,
})

template.html:

<div class="container">
  <form action="{% url 'app:formAllView' truck=truck %}" class="form" method="post">
    {{ form1 }}
    {{ form2 }}
    {{ form3 }}
    {{ form4 }}
    # Either put the submit in the form here manually or in the form4 template
  </form>

forms.py

# create a shared 
class BaseSharedClass(forms.ModelForm):
  def save(self, commit=True):
  """Save the instance, but not to the DB jsut yet"""
  obj = super(WIBaseClass, self).save(commit=False)
  if commit:
    obj.currentUser = self.currentUser
    obj.truck = self.truck
    obj.save()
  return obj
def __init__(self, *args, **kwargs):
  self.currentUser = kwargs.pop('currentUser', None)
  self.truck = kwargs.pop('truck', None)
  super(WIBaseClass, self).__init__(*args, **kwargs)

#note inherting the base shared class
class form1Form(BaseSharedClass):
  def __init__(self, *args, **kwargs):
    super(form1Form, self).__init__(*args, **kwargs)

THE IMPORTANT PARTS

When Architecting the forms in the forms.py

  • Overall
    • Make a parent class (BaseSharedClass) that all forms that need shared information will inherit from
    • Extend all the forms that need the shared info from the parent class (class form1Form(BaseSharedClass) )
  • With regard to init-ing
    • remove the shared objects from the form, to avoid duplications of the shared fields across all of the forms that will be in the same page (self.currentUser = kwargs.pop('currentUser', None) && self.truck = kwargs.pop('truck', None) )
  • With regard to Saving
    • override the save function to do the magic
    • make commit=false to prevent it from saving just yet
    • add the related fields from the passed in context ( obj.currentUser = self.currentUser && obj.truck = self.truck ), and then save (obj.save() )

When creating the form in the view:

  • pass it the instance of the shared object instance=truck. You can also pass other objects if you need access to them as well, such as relatedObject=queriredObject
  • Pass in the prefix prefix=formIdentifierN, as this helps Django keep track of what unique information, fields, entries are associated with which forms. No special naming is needed, and form1, form2, etc... works well, so long as you know which are each.

When saving the form in the view:

  • everything here is the same (saving, error handling, etc...) as a single form, but you can check it in one line with all( [a,b,c,d] )
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!