个人博客,欢迎查看:https://blog.starmeow.cn/
Github地址:https://github.com/xyliurui/DjangoCRM
只读字段readonly_fields处理
创建注册模型类字段
修改djadmin应用下的djadmin_base.py中的BaseDjAdmin(object)
增加readonly_fields
字段,用于处理只读字段
# djadmin/djadmin_base.py
class BaseDjAdmin(object):
list_display = []
list_filter = []
search_fields = []
readonly_fields = []
增加应用注册类制度字段
修改crm应用下的djadmin.py,增加只读字段
# 注册model
class CustomerInfoAdmin(BaseDjAdmin): # 不使用object,直接继承BaseDjAdmin
list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
list_filter = ['source', 'consultant', 'status', 'created_time']
search_fields = ['contact', 'consultant__name', 'consult_content']
readonly_fields = ['contact', 'status']
动态生成表单排除只读字段
修改djadmin应用下的form_handle.py中的函数create_dynamic_model_form(admin_class)
,为其增加排除字段
from django.forms import ModelForm
def create_dynamic_model_form(admin_class):
"""动态生成ModelF"""
class Meta:
model = admin_class.model
fields = '__all__'
exclude = admin_class.readonly_fields
# 通过__new__(cls, *arg, **kwargs)方法,找到ModelForm里面的每个字段,然后循环出每个字段并添加自定义样式
def __new__(cls, *args, **kwargs):
# cls.base_fields是一个元组,格式为:OrderedDict([('字段名', 字段的对象), ()])
# print(cls.base_fields)
# OrderedDict([('user', <django.forms.models.ModelChoiceField object at 0x000002147D024358>), ('name', <django.forms.fields.CharField object at 0x000002147D0243C8>), ('role', <django.forms.models.ModelMultipleChoiceField object at 0x000002147D0245C0>)])
for field_name in cls.base_fields:
# 每个字段的对象
field_obj = cls.base_fields[field_name]
# 添加属性
field_obj.widget.attrs.update({'class': 'form-control'})
return ModelForm.__new__(cls)
# 动态生成
dynamic_form = type('DynamicModelForm', (ModelForm,), {'Meta': Meta, '__new__': __new__})
return dynamic_form
如果是只读字段后端就排除掉,然后通过前端把只读字段显示在页面(放在p标签里面,这样修改form的时候就不会验证只读字段,模仿Django admin的做法)
image.png如果CustomerInfoAdmin(BaseDjAdmin)中没有readonly_fields = ['contact', 'status']
字段,则就会显示联系方式
和客户状态
表单
模板标签显示只读字段值
创建模板标签,用于显示这些只读字段的值
修改djadmin应用下的templatetags包中的djadmin_tags.py,增加获取只读字段的函数
@register.simple_tag
def get_obj_field_val(form_obj, field):
"""获取只读字段的值"""
return getattr(form_obj.instance, field)
然后修改djadmin下templates/djadmin/table_edit.html文件,增加显示只读字段
{% extends 'djadmin/base.html' %}
{% load djadmin_tags %}
{% block title %}
数据表编辑 - 后台管理
{% endblock %}
{% block content %}
<h1 class="page-header">{{ app_name }} - {{ model_name }} - 编辑 {{ obj }} </h1>
<!--<div>{{ form_obj }}</div>-->
<form class="form-horizontal" method="post">
{{ form_obj.errors }}
{% for field in form_obj %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-10">
{{ field }}
<span style="color: red">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
{% csrf_token %}
{% for field in admin_class.readonly_fields %}
<label class="col-sm-2 control-label">{{ field }}</label>
<div class="col-sm-10">
<p>{% get_obj_field_val form_obj field %}</p>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
{% endblock %}
访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/1/change/ 可以保存修改
image.png现在修改没有问题了,但是在添加的时候报错
访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/add/ 增加
image.png提示那两个只读字段为空,因为设置成了readonly_field
,添加的时候确实没有添加值
添加数据只读字段报错
解决设置字段字段后添加数据报错,在前后端都添加一个判断
添加数据视图增加form_add传参
修改djadmin应用的添加数据视图able_add(request, app_name, model_name)
,在创建动态表单是设置一个form_add
参数值为True,修改数据不用改,因为动态表单生成有一个默认值
# 数据添加
@login_required
def table_add(request, app_name, model_name):
from .form_handle import create_dynamic_model_form
admin_class = site.enable_admins[app_name][model_name]
model_form = create_dynamic_model_form(admin_class=admin_class, form_add=True) # 增加数据设置form_add为True
form_obj = model_form()
if request.method == 'POST':
form_obj = model_form(data=request.POST)
if form_obj.is_valid():
form_obj.save()
return redirect(reverse('djadmin:table_detail', kwargs={'app_name': app_name, 'model_name': model_name}))
return render(request, 'djadmin/table_edit.html', locals())
修改动态表单form_add参数判断
修改djadmin应用的form_handle.py文件,动态创建表单,增加form_add
判断,如果为True,则不使用排除字段
from django.forms import ModelForm
def create_dynamic_model_form(admin_class, form_add=False):
"""动态生成ModelForm,根据form_add字段判断是修改数据还是增加数据,如果修改,form_add为False"""
class Meta:
model = admin_class.model
fields = '__all__'
# 根据form_add判断是否是增加还是修改
admin_class.form_add = form_add # 用于前端传值判断,默认为False,当增加数据是变为True
if not form_add: # form_add为False,则修改
exclude = admin_class.readonly_fields
# 通过__new__(cls, *arg, **kwargs)方法,找到ModelForm里面的每个字段,然后循环出每个字段并添加自定义样式
def __new__(cls, *args, **kwargs):
# cls.base_fields是一个元组,格式为:OrderedDict([('字段名', 字段的对象), ()])
# print(cls.base_fields)
# OrderedDict([('user', <django.forms.models.ModelChoiceField object at 0x000002147D024358>), ('name', <django.forms.fields.CharField object at 0x000002147D0243C8>), ('role', <django.forms.models.ModelMultipleChoiceField object at 0x000002147D0245C0>)])
for field_name in cls.base_fields:
# 每个字段的对象
field_obj = cls.base_fields[field_name]
# 添加属性
field_obj.widget.attrs.update({'class': 'form-control'})
return ModelForm.__new__(cls)
# 动态生成
dynamic_form = type('DynamicModelForm', (ModelForm,), {'Meta': Meta, '__new__': __new__})
return dynamic_form
修改编辑模板form_add参数判断
修改djadmin应用的templates/djadmin/table_edit.html,增加增加或修改数据判断,如果是修改数据,form_add
为False,则显示只读字段;如果是增加数据,form_add
为True,则把所有表单显示出来
{% extends 'djadmin/base.html' %}
{% load djadmin_tags %}
{% block title %}
数据表编辑 - 后台管理
{% endblock %}
{% block content %}
<h1 class="page-header">{{ app_name }} - {{ model_name }} - 编辑 {{ obj }} </h1>
<!--<div>{{ form_obj }}</div>-->
<form class="form-horizontal" method="post">
{{ form_obj.errors }}
{% for field in form_obj %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-10">
{{ field }}
<span style="color: red">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
{% csrf_token %}
{% if not admin_class.form_add %}
{# 当修改数据时,才显示下方只读字段,当增加数据时,下方则不会显示 #}
{% for field in admin_class.readonly_fields %}
<label class="col-sm-2 control-label">{{ field }}</label>
<div class="col-sm-10">
<p>{% get_obj_field_val form_obj field %}</p>
</div>
{% endfor %}
{% endif %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
{% endblock %}
现在增加数据和修改数据都可以正常使用了。
网友评论