您现在的位置是: 网站首页 >Django >DjangoCRM客户关系管理 Django
【CRM客户关系管理】16. 只读字段readonly_fields处理,表单排除只读显示
admin2018年12月4日 15:08 【Django | Html | Python 】 1126人已围观
DjangoCRM客户关系管理简介 使用Django2.1.3+Bootstrap实现CRM系统,仿照Django Admin重写后台 Github地址:https://github.com/xyliurui/DjangoCRM Django版本:2.1.3
## 只读字段readonly_fields处理 ### 创建注册模型类字段 修改djadmin应用下的djadmin_base.py中的`BaseDjAdmin(object)`增加`readonly_fields`字段,用于处理只读字段 ```python # djadmin/djadmin_base.py class BaseDjAdmin(object): list_display = [] list_filter = [] search_fields = [] readonly_fields = [] ``` #### 增加应用注册类制度字段 修改crm应用下的djadmin.py,增加只读字段 ```python # 注册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)`,为其增加排除字段 ```python 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的做法) ![BLOG_20181204_151305_34](/media/blog/images/2018/12/BLOG_20181204_151305_34.png "博客图集BLOG_20181204_151305_34.png") 如果CustomerInfoAdmin(BaseDjAdmin)中没有`readonly_fields = ['contact', 'status']`字段,则就会显示`联系方式`和`客户状态`表单 ![BLOG_20181204_151246_41](/media/blog/images/2018/12/BLOG_20181204_151246_41.png "博客图集BLOG_20181204_151246_41.png") ### 模板标签显示只读字段值 创建模板标签,用于显示这些只读字段的值 修改djadmin应用下的templatetags包中的djadmin_tags.py,增加获取只读字段的函数 ```python @register.simple_tag def get_obj_field_val(form_obj, field): """获取只读字段的值""" return getattr(form_obj.instance, field) ``` 然后修改djadmin下templates/djadmin/table_edit.html文件,增加显示只读字段 ```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/ 可以保存修改 ![BLOG_20181204_151232_83](/media/blog/images/2018/12/BLOG_20181204_151232_83.png "博客图集BLOG_20181204_151232_83.png") 现在修改没有问题了,但是在添加的时候报错 访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/add/ 增加 ![BLOG_20181204_151203_46](/media/blog/images/2018/12/BLOG_20181204_151203_46.png "博客图集BLOG_20181204_151203_46.png") 提示那两个只读字段为空,因为设置成了`readonly_field`,添加的时候确实没有添加值 ### 添加数据只读字段报错 解决设置字段字段后添加数据报错,在前后端都添加一个判断 #### 添加数据视图增加form_add传参 修改djadmin应用的添加数据视图`able_add(request, app_name, model_name)`,在创建动态表单是设置一个`form_add`参数值为True,修改数据不用改,因为动态表单生成有一个默认值 ```python # 数据添加 @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,则不使用排除字段 ```python 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,则把所有表单显示出来 ```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 %} {% 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 %} ``` 现在增加数据和修改数据都可以正常使用了。
很赞哦! (0)
相关文章
文章交流
- emoji
当前用户
未登录,点击 登录专题目录
- 【CRM客户关系管理】01.项目介绍分析
- 【CRM客户关系管理】02.设置项目需要的模型
- 【CRM客户关系管理】03.使用Bootstrap前端模板
- 【CRM客户关系管理】04.用户登录登录及访问控制
- 【CRM客户关系管理】05.动态菜单生成,绝对URL和动态URL
- 【CRM客户关系管理】06.创建djadmin APP,并进行相关配置
- 【CRM客户关系管理】07.自动发现APP注册并显示列表
- 【CRM客户关系管理】08.取出app中model的值,根据list_display配置生成数据列表
- 【CRM客户关系管理】09.根据模型中字段的choices以及时间区间来过滤数据
- 【CRM客户关系管理】10.处理无list_display和list_filter属性时的异常情况
- 【CRM客户关系管理】11.为查询结果添加分页和排序功能
- 【CRM客户关系管理】12.查询结果分页、排序、过滤组合
- 【CRM客户关系管理】13.为结果添加搜索功能,搜索后能对其进行过滤
- 【CRM客户关系管理】14.生成动态ModelForm表单功能
- 【CRM客户关系管理】15.动态ModelsForm增加自定义样式,修改初始化表单并提交
- 【CRM客户关系管理】16. 只读字段readonly_fields处理,表单排除只读显示
- 【CRM客户关系管理】17.多选字段filter_horizontal的实现,已选和未选数据展示
- 【CRM客户关系管理】18.多选字段filter_horizontal的实现,js移动多选框数据和过滤
- 【CRM客户关系管理】19.对象删除功能,显示删除的关联对象和确认
- 【CRM客户关系管理】20.增加详情页分页功能
- 【CRM客户关系管理】21.action功能开发,默认action,生成自己的action
- 【CRM客户关系管理】22.action功能开发,执行action功能,添加默认的delete action