嵌套和分段的脆皮布局
Nested and Segmented Crispy Layouts
TLDR 问题:如何制作带有“分段”的脆皮表格?(不确定这是否被视为内联)布局与多个模型(一些相关,一些不相关)。
我正在尝试理解 Django 中的几个东西:表单、表单集、嵌套表单和 crispy,我已经研究了一段时间,感觉自己很接近,只是需要有人帮助连接点.我不确定如何在没有脆皮的情况下完成它,所以我开始走这条路,认为脆皮是解决方案。如有错误请指正,谢谢:)
我想要一种形式(如 HTML 形式,不一定是 Django 形式),它有一个包含很多字段的主模型,但在主模型中间有 secondary/tertiary 个模型领域。我非常接近布局,但似乎无法让 secondary/tertiary 模型在布局中间呈现,更不用说在没有 crispy/django 错误的情况下进行编译了。
这是我想要达到的目标的颜色编码视觉效果
我认为我至少有以下一项是错误的:
- 我没有调用正确的 formfactory
- 我没有正确使用表单集
- 我没有在表单助手的布局中将表单字段正确引用到正确的模型字段
- 无法进行布局,或者我应用了错误的代码结构来获取结果。
- 我不认为我可以直接在下面调用两个表单,因为它们不会nested/integrated
上面列表项的代码(不能将代码块直接放在下面
#I don't think this will achieve the integration/nested look I am aiming for
#views.py:
parent_form = ParentForm()
child_form = ChildForm()
render(template.html, {
"pform": parent_form,
"cform": child_form
})
#template.html:
<form>
{{ pform }}
{{ cform }}
</form>
文件供参考
models.py
#Black in the picture
class Truck(models.Model):
name = models.CharField(…)
…
#Blue in the picture
class QuickInspection(models.Model):
odometer = models.IntegerField(…)
… (created_at, user_cookie#who did it, …)
truck = models.ForeignKey(Truck)
-----
#These two are unrelated to the Truck in the DB, and I would prefer to keep it that way, if for at least to understand how to accomplish this
-----
#Red
class Tires(models.Model):
front_tire = models.CharField(…)
… (created_at, …)
truck = models.ForeignKey(Truck)
full_inspection = models.ForeignKey(FullInspection, blank=True, null=True) #optional, and if it has this foreign key, then I know the Tires were looked at in a full inspection. If not, then they were looked at in the quick inspection, without having a foreign key to the QuickInspection
#Green
class Brakes(models.Model):
front_axle = models.CharField(…)
…
createdAt = models.DateTimeField(auto_now_add=True)
truck = models.ForeignKey(Truck)
pm = models.ForeignKey(PM, blank=True, null=True)
full_inspection = models.ForeignKey(FullInspection, blank=True, null=True) #optional, same as full_inspection in Tires
views.py
def weeklyView(request, truckID):
# POST
if request.method == 'POST':
# Check forms for valid data and save or provide error
#return response
# GET
else:
#make each form individually?
quickForm = OHReadingForm(…)
tireForm = TireForm()
brakeForm = BrakeForm()
#Or import a formset and helper?
formset = ExampleFormSet()
helper = ExampleFormSetHelper()
response = render(request, 'trucks/weeklyInspection.html', {
'ohrForm': ohrForm,
'formset': formset,
'helper': helper,
'tireForm': tireForm,
'truck': truck,
})
forms.py
class QuickInspectionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(QuickInspectionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_method = 'post'
self.helper.form_action = 'quickInspectionURL'
self.helper.layout = Layout(
Div(
Div(
Fieldset(
'', # 'first arg is the legend of the fieldset',
'quickInspectionMetric1', #From QuickInspection.metric1
'quickInspectionMetric2', #From QuickInspection.metric2
'quickInspectionMetric3', #From QuickInspection.metric3
),
css_class="blue"
),
Div(
Fieldset(
'tireMetric1', #from Tire.metric1
'tireMetric2', #from Tire.metric2
css_class="red"
),
Div(
Fieldset(
'brakeMetric1', #from Brake.metric1
'brakeMetric2', #from Brake.metric2
css_class="green"
),
Div(
Fieldset(
'quickInspectionMetric4', #from QuickInspection.metric4
'quickInspectionMetric5', #from QuickInspection.metric5
css_class="blue"
),
),
Div(
FormActions(
Reset('reset', 'Reset'),
Submit('submit', 'Submit') #submit for all
)
),
)
class Meta:
model = QuickInspection
fields = [
'metric1','metric2','metric3','metric4','metric5',
'truck',
…,
]
ExampleFormSet = formset_factory(QuickInspectionForm, extra=1)
# Other failed attempts
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, extra=1)
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, TireForm, extra=1)
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, TireForm, BrakeForm, extra=1)
class ExampleFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(ExampleFormSetHelper, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.form_tag = False
self.layout = Layout(…)
#Same as Brake Form
class TireForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TCForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = 'tireURL'
self.helper.layout = Layout(…)
class Meta:
model = TireCondition
fields = [
'metric1', 'metric2', …
'truck',
]
JS fiddle for code repo。我不知道类似 DJango 的 Fiddle 环境...
脆皮与这个问题无关。表单可以包含在模板中:
{{form1}}
{{form2}}
...
或
{% crispy form1 form1.helper %} #although the helper name here is default and not needed
{% crispy form2 %} # form2.helper is implied
...
对于假设:
- 我没有调用正确的 formfactory
- 不需要表单工厂,因为任何一个表单都没有多个版本
- 我没有正确使用表单集
- 也不需要,因为没有任何单一形式的多个版本
- 我没有在表单助手的布局中将表单字段正确引用到正确的模型字段
- 有点真实
- 无法进行布局,或者我应用了错误的代码结构来获得结果。
- 请参阅下面的答案
- 我不认为我可以直接在下面调用两个表单,因为它们不会nested/integrated
- 一个可以,见下文
使用相关 objects/foreign 键创建集成表单的代码:
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)
重要部分
在 forms.py
中构建表单时
- 总体
- 创建父类 class (BaseSharedClass),所有需要共享信息的表单都将继承自
- 扩展所有需要父级共享信息的表单 class (class form1Form(BaseSharedClass) )
- 关于初始化
- 从表单中删除共享对象,以避免同一页面中所有表单的共享字段重复 (self.currentUser = kwargs.pop('currentUser' , None) && self.truck = kwargs.pop('truck', None) )
- 关于储蓄
- 重写保存函数来施展魔法
- 制作
commit=false
以防止它刚刚保存
- 从传入的上下文中添加相关字段(obj.currentUser = self.currentUser && obj.truck = self.truck),然后保存(obj.save( ))
在视图中创建表单时:
- 将共享对象的实例传递给它
instance=truck
。如果您还需要访问其他对象,您也可以传递它们,例如 relatedObject=queriredObject
- 传入前缀
prefix=formIdentifierN
,因为这有助于 Django 跟踪哪些唯一信息、字段、条目与哪些表单相关联。不需要特殊的命名,并且 form1、form2 等...都可以正常工作,只要您知道它们分别是什么即可。
在视图中保存表单时:
- 此处的所有内容(保存、错误处理等)都与单个表单相同,但您可以使用
all( [a,b,c,d] )
在一行中检查它
TLDR 问题:如何制作带有“分段”的脆皮表格?(不确定这是否被视为内联)布局与多个模型(一些相关,一些不相关)。
我正在尝试理解 Django 中的几个东西:表单、表单集、嵌套表单和 crispy,我已经研究了一段时间,感觉自己很接近,只是需要有人帮助连接点.我不确定如何在没有脆皮的情况下完成它,所以我开始走这条路,认为脆皮是解决方案。如有错误请指正,谢谢:)
我想要一种形式(如 HTML 形式,不一定是 Django 形式),它有一个包含很多字段的主模型,但在主模型中间有 secondary/tertiary 个模型领域。我非常接近布局,但似乎无法让 secondary/tertiary 模型在布局中间呈现,更不用说在没有 crispy/django 错误的情况下进行编译了。
这是我想要达到的目标的颜色编码视觉效果
我认为我至少有以下一项是错误的:
- 我没有调用正确的 formfactory
- 我没有正确使用表单集
- 我没有在表单助手的布局中将表单字段正确引用到正确的模型字段
- 无法进行布局,或者我应用了错误的代码结构来获取结果。
- 我不认为我可以直接在下面调用两个表单,因为它们不会nested/integrated
上面列表项的代码(不能将代码块直接放在下面
#I don't think this will achieve the integration/nested look I am aiming for
#views.py:
parent_form = ParentForm()
child_form = ChildForm()
render(template.html, {
"pform": parent_form,
"cform": child_form
})
#template.html:
<form>
{{ pform }}
{{ cform }}
</form>
文件供参考
models.py
#Black in the picture
class Truck(models.Model):
name = models.CharField(…)
…
#Blue in the picture
class QuickInspection(models.Model):
odometer = models.IntegerField(…)
… (created_at, user_cookie#who did it, …)
truck = models.ForeignKey(Truck)
-----
#These two are unrelated to the Truck in the DB, and I would prefer to keep it that way, if for at least to understand how to accomplish this
-----
#Red
class Tires(models.Model):
front_tire = models.CharField(…)
… (created_at, …)
truck = models.ForeignKey(Truck)
full_inspection = models.ForeignKey(FullInspection, blank=True, null=True) #optional, and if it has this foreign key, then I know the Tires were looked at in a full inspection. If not, then they were looked at in the quick inspection, without having a foreign key to the QuickInspection
#Green
class Brakes(models.Model):
front_axle = models.CharField(…)
…
createdAt = models.DateTimeField(auto_now_add=True)
truck = models.ForeignKey(Truck)
pm = models.ForeignKey(PM, blank=True, null=True)
full_inspection = models.ForeignKey(FullInspection, blank=True, null=True) #optional, same as full_inspection in Tires
views.py
def weeklyView(request, truckID):
# POST
if request.method == 'POST':
# Check forms for valid data and save or provide error
#return response
# GET
else:
#make each form individually?
quickForm = OHReadingForm(…)
tireForm = TireForm()
brakeForm = BrakeForm()
#Or import a formset and helper?
formset = ExampleFormSet()
helper = ExampleFormSetHelper()
response = render(request, 'trucks/weeklyInspection.html', {
'ohrForm': ohrForm,
'formset': formset,
'helper': helper,
'tireForm': tireForm,
'truck': truck,
})
forms.py
class QuickInspectionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(QuickInspectionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_method = 'post'
self.helper.form_action = 'quickInspectionURL'
self.helper.layout = Layout(
Div(
Div(
Fieldset(
'', # 'first arg is the legend of the fieldset',
'quickInspectionMetric1', #From QuickInspection.metric1
'quickInspectionMetric2', #From QuickInspection.metric2
'quickInspectionMetric3', #From QuickInspection.metric3
),
css_class="blue"
),
Div(
Fieldset(
'tireMetric1', #from Tire.metric1
'tireMetric2', #from Tire.metric2
css_class="red"
),
Div(
Fieldset(
'brakeMetric1', #from Brake.metric1
'brakeMetric2', #from Brake.metric2
css_class="green"
),
Div(
Fieldset(
'quickInspectionMetric4', #from QuickInspection.metric4
'quickInspectionMetric5', #from QuickInspection.metric5
css_class="blue"
),
),
Div(
FormActions(
Reset('reset', 'Reset'),
Submit('submit', 'Submit') #submit for all
)
),
)
class Meta:
model = QuickInspection
fields = [
'metric1','metric2','metric3','metric4','metric5',
'truck',
…,
]
ExampleFormSet = formset_factory(QuickInspectionForm, extra=1)
# Other failed attempts
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, extra=1)
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, TireForm, extra=1)
# ExampleFormSet = inlineformset_factory(QuickInspectionForm, TireForm, BrakeForm, extra=1)
class ExampleFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(ExampleFormSetHelper, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.form_tag = False
self.layout = Layout(…)
#Same as Brake Form
class TireForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TCForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = 'tireURL'
self.helper.layout = Layout(…)
class Meta:
model = TireCondition
fields = [
'metric1', 'metric2', …
'truck',
]
JS fiddle for code repo。我不知道类似 DJango 的 Fiddle 环境...
脆皮与这个问题无关。表单可以包含在模板中:
{{form1}}
{{form2}}
...
或
{% crispy form1 form1.helper %} #although the helper name here is default and not needed
{% crispy form2 %} # form2.helper is implied
...
对于假设:
- 我没有调用正确的 formfactory
- 不需要表单工厂,因为任何一个表单都没有多个版本
- 我没有正确使用表单集
- 也不需要,因为没有任何单一形式的多个版本
- 我没有在表单助手的布局中将表单字段正确引用到正确的模型字段
- 有点真实
- 无法进行布局,或者我应用了错误的代码结构来获得结果。
- 请参阅下面的答案
- 我不认为我可以直接在下面调用两个表单,因为它们不会nested/integrated
- 一个可以,见下文
使用相关 objects/foreign 键创建集成表单的代码:
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)
重要部分
在 forms.py
中构建表单时- 总体
- 创建父类 class (BaseSharedClass),所有需要共享信息的表单都将继承自
- 扩展所有需要父级共享信息的表单 class (class form1Form(BaseSharedClass) )
- 关于初始化
- 从表单中删除共享对象,以避免同一页面中所有表单的共享字段重复 (self.currentUser = kwargs.pop('currentUser' , None) && self.truck = kwargs.pop('truck', None) )
- 关于储蓄
- 重写保存函数来施展魔法
- 制作
commit=false
以防止它刚刚保存 - 从传入的上下文中添加相关字段(obj.currentUser = self.currentUser && obj.truck = self.truck),然后保存(obj.save( ))
在视图中创建表单时:
- 将共享对象的实例传递给它
instance=truck
。如果您还需要访问其他对象,您也可以传递它们,例如relatedObject=queriredObject
- 传入前缀
prefix=formIdentifierN
,因为这有助于 Django 跟踪哪些唯一信息、字段、条目与哪些表单相关联。不需要特殊的命名,并且 form1、form2 等...都可以正常工作,只要您知道它们分别是什么即可。
在视图中保存表单时:
- 此处的所有内容(保存、错误处理等)都与单个表单相同,但您可以使用
all( [a,b,c,d] )
在一行中检查它