如何动态的生成 ModelForm
2018-12-22 本文已影响0人
摘花是个好习惯
在项目中新建 forms.py文件
from django import forms
def create_model_form(request,admin_class):
'''动态生成Model Form'''
# 修改样式
def __new__(cls, *args, **kwargs):
#print(cls.base_fields) OrderedDict([('name', <django.forms.fields.CharField object at 0x000001385625DA90>)]),
for field_name,field_obj in cls.base_fields.items():
# 根据 cls.base_field 的特性给每个字段加上样式
cls.base_fields[field_name].widget.attrs['class'] = 'form-control'
return forms.ModelForm.__new__(cls)
class Meta:
model = admin_class.model # 通过admin_class动态获取model
# fields = ('name', 'qq') # 可以获取指定字段
# age = forms.IntegerField() # 还可以添加字段
fields = '__all__' # '__all__'获取所有字段
attrs = {'Meta':Meta}
_model_form_class = type("DynamicModelForm", (forms.ModelForm,), attrs) # 第一个参数是类名,第二个参数是元组,填写父类,最后必须添加逗号,
# 第三个参数字典形式的Meta类
# 方法一定要 setattr
setattr(_model_form_class,'__new__',__new__)
return _model_form_class # 返回的是一个类
在视图函数中调用 forms.create_model_form()
model_form_class 的两个参数
- instance : 将表对象实例到前端,使用这个参数后前端的输入框会默认填充修改前的值
- request.POST:提交表单后,如果不传入request.POST 会变成新建表对象的效果
def table_obj_change(request,app_name,table_name,obj_id):
admin_class = king_admin.enabled_admins[app_name][table_name]
model_form_class = forms.create_model_form(request, admin_class)
# 根据后端传入的id获得要修改的表对象
obj = admin_class.model.objects.get(id=obj_id)
# 表单提交后重新调用 create_model_form(),并且把request.POST传进去
if request.method == 'POST':
form_obj = model_form_class(request.POST, instance=obj)
# 前端填写的数据没有异常就保存
if form_obj.is_valid():
# ModelForm的方式可以直接 save 保存
form_obj.save()
# 通过反转回到 table_name 表
return redirect(reverse('table_obj',kwargs={'app_name':app_name,'table_name':table_name}))
else:
form_obj = model_form_class(instance=obj)
return render(request, 'king_admin/table_obj_change.html', {'form_obj':form_obj})
前端
required : 判断字段是否能为空,不能为空为True
实现字段的 label 根据非空显示字体粗细的方法:
由于django的表单方法会默认给 字段的 label 加粗,所以给 div 一个 style="font-weight: normal",再循环表单对象, 使用 field.required 判断字段是否为空,给不能为空的添加<b>标签
<form class="form-horizontal" method="POST">
{% for field in form_obj %}
<div class="form-group">
<div class="col-md-8" style="font-weight: normal">
<div class="col-md-2 col-md-offset-1" >
{% if field.field.required %}
<b>{{ field.label }}</b>
{% else %}
{{ field.label }}
{% endif %}
</div>
<div class="col-md-6">
{{ field }}
</div>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-success pull-right" style="margin-bottom: 50px">save</button>
</form>