我知道您可以在django中为Admin帮助程序指定字段集。但是,我找不到任何对ModelForms有用的东西。只是一些我无法使用的补丁。我错过了什么吗?有没有一种方法可以实现像fieldset这样的东西,而无需在相应的标签中手动写出模板上的每个字段。
我希望迭代一组BoundFields。但是,在我的ModelForm结尾处做这样的事情:
fieldsets = []
fieldsets.append(('Personal Information',
[username,password,password2,first_name,last_name,email]),) # add a 2 element tuple of string and list of fields
fieldsets.append(('Terms & Conditions',
[acceptterms,acceptprivacy]),) # add a 2 element tuple of string and list of fields
失败,因为我的数据结构中包含的项目是原始字段,而不是BoundFields。看起来像动态生成的BoundFields ......这让我感到难过。我可以创建自己的forms.Form子类,其中包含一个fieldsets的概念(即使是一个不向后兼容的粗略的...这只适用于我自己的项目)如果是这样,你能给出任何指针吗?我不想乱用django代码。
答案 0 :(得分:50)
我认为this snippet完全符合您的要求。它为您提供了一个Form子类,允许您以声明方式将表单细分为字段集,并在模板中迭代它们。
更新:该代码段已成为django-form-utils
的一部分答案 1 :(得分:34)
模型中的场集仍处于“设计”阶段。 Django trac中存在ticket,活动性较低。
这是我一直对在不久的将来研究自己感兴趣的东西,但是由于我还没有做到,我能提供的最好的是这些片段:
编辑:我刚刚再次注意到这个问题,我意识到需要编辑才能指出Carl的项目django-form-utils,其中包含一个可以包含fieldsets的BetterForm类。如果您喜欢这个项目,请在下面给他+1答案:)
答案 2 :(得分:16)
您可以做的一件事是将逻辑字段集分成单独的模型表单类。
class PersonalInfoForm (forms.ModelForm):
class Meta:
model=MyModel
fields=('field1', 'field2', ...)
class TermsForm (forms.ModelForm):
class Meta:
model=MyModel
fields=('fieldX', 'fieldY', ...)
将它们传递给不同变量的模板并分解表格集:
<form ...>
<fieldset><legend>Personal Information</legend>
{{ personal_info_form }}
</fieldset>
<fieldset><legend>Terms and Conditions</legend>
{{ terms_form }}
</fieldset>
</form>
从这个意义上讲,每个表单类只是实际HTML表单的一个片段。
当您在表单上调用save时,它会带来一丝复杂性。您可能希望传递commit = False,然后合并结果对象。或者完全避免使用ModelForm.save并使用'cleaning_data'手动填充模型对象
答案 3 :(得分:4)
Daniel Greenfelds django-uni-form使用布局辅助类解决了这个问题。我现在正在尝试它,它看起来很干净。
我最初选择了Django-uni-form,因为它符合section 508。
答案 4 :(得分:0)
这是我为了解自定义标签(带链接)而开发的代码。我应用它来创建一个字段集。
免责声明:我鼓励使用上述任何答案,这只是为了学习。
templatetags/myextras.py
:
from django import template
from django.template import Context
register = template.Library()
class FieldsetNode(template.Node):
""" Fieldset renderer for 'fieldset' tag """
def __init__(self, nodelist, fieldset_name):
""" Initialize renderer class
https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-renderer
:param nodelist: a list of the template nodes inside a block of 'fieldset'
:param fieldset_name: the name of the fieldset
:return: None
"""
self.nodelist = nodelist
self.fieldset_name = fieldset_name
def render(self, context):
""" Render the inside of a fieldset block based on template file
https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#auto-escaping-considerations
:param context: the previous template context
:return: HTML string
"""
t = context.template.engine.get_template('myapp/fieldset.html')
return t.render(Context({
'var': self.nodelist.render(context),
'name': self.fieldset_name,
}, autoescape=context.autoescape))
@register.tag
def fieldset(parser, token):
""" Compilation function for fieldset block tag
Render a form fieldset
https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-compilation-function
https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#parsing-until-another-block-tag
:param parser: template parser
:param token: tag name and variables
:return: HTML string
"""
try:
tag_name, fieldset_name = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0])
if not (fieldset_name[0] == fieldset_name[-1] and fieldset_name[0] in ('"', "'")):
raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
nodelist = parser.parse(('endfieldset',))
parser.delete_first_token()
return FieldsetNode(nodelist, fieldset_name[1:-1])
templates/myapp/fieldset.html
:
<div class="fieldset panel panel-default">
<div class="panel-heading">{{ name }}</div>
<div class="panel-body">{{ var }}</div>
</div>
templates/myapp/myform.html
:
<form action="{% url 'myapp:myurl' %}" method="post">
{% csrf_token %}
{% fieldset 'General' %}
{{form.myfield1 }}
{% endfieldset %}
{# my submit button #}
</form>
答案 5 :(得分:0)
您可以使用这个包:https://pypi.org/project/django-forms-fieldset/
pip install django-forms-fieldset
将 forms_fieldset 添加到您的 INSTALLED_APPS 设置中,如下所示:
INSTALLED_APPS = [
...
'forms_fieldset',
]
在表单中添加 fieldsets
from django.forms import ModelForm
from .models import Student
class StudentForm(ModelForm):
fieldsets = [
("Student Information", {'fields': [
('first_name', 'last_name'),
('email', 'adress'),
]}),
("Parent Information", {'fields': [
'mother_name',
'father_name',
]}),
]
class Meta:
model = Student
fields = '__all__'
在你看来
def home(request):
form = StudentForm()
if request.method == 'POST':
form = Form(request.POST, request.FILES)
#save...
context = {
'form': form,
}
return render(request, 'home.html', context)
在您的模板中
{% load forms_fieldset static %}
<link rel="stylesheet" type="text/css" href="{% static 'forms_fieldset/css/main.css' %}">
<form>
{{ form|fieldset:'#42945c' }}
</form>