zoukankan      html  css  js  c++  java
  • Python CRM项目七

    仿照Django Admin实现对readonly的字段进行设置

    功能点:

      1.页面不可进行更改

      2.如果改变html代码中的值,则需要进行后端的数据库数据校验

      3.可以对某些字段进行自定制校验规则

    一.页面展示该字段不可更改

    思路:

      1.在king_admin中的自定义admin_class中配置不可更改的列

      2.在forms中循环views传递的admin_class中的readonly_fields,如果有则在__init__方法中加入disabled

           3.在前端循环展示

    1.在每个admin_class中添加readonly_fields属性

    class CustomerAdmin(BaseAdmin):
        list_display = ['qq','name','source','consultant','consult_course','date','status']
        list_filters = ['source','consultant','consult_course','status','date']
        search_fields = ['qq','name','consultant__name']
        list_per_page = 5
        ordering = 'id'
        filter_horizontal = ['tags',]
        actions = ['delete_selected_objs','test',]
        readonly_fields = ['qq','consultant','tags',] #写上不可被修改的字段

    2.在__new__方法中添加readonly字段的disabled属性

        def __new__(cls,*args,**kwargs):
            #动态生成样式
            for field_name,field_obj in cls.base_fields.items():
    #
    给所有的字段加上form-control样式 field_obj.widget.attrs['class'] = 'form-control' if field_name in admin_class.readonly_fields:
    #如果字段是readonly字段,则加上disabled样式,这样在前端展示的时候,显示为不可更改 field_obj.widget.attrs[
    'disabled'] = 'disabled' if hasattr(admin_class,'clean_%s'%field_name):
    #获取admin_class中的自定义的字段校验方法,加入到自动生成的类中 field_clean_func
    =getattr(admin_class,'clean_%s'%field_name) setattr(cls,'field_clean_func',field_clean_func) return ModelForm.__new__(cls)

    3.前端展示

    单个字段展示,包含外键

    <label class="col-sm-2 control-label" style="font-weight:normal">
    {#自动从后端生成的model_form获取field字段进行展示#}
    {% if field.field.required %} <b>{{ field.label }}</b> {% else %} {{ field.label }} {% endif %} </label>

    多对多复选框展示

    如果多对多字段在admin_class中的readonly_field中,那么手动给其option加上disabled样式,同时删除js时间,将其的值锁定,不可在改变

    {% if field.name in admin_class.filter_horizontal %}
    {#实现和Django类似的复选框#}
        <div class="col-md-4">
            {% get_m2m_tags  admin_class field form_obj as m2m_obj_tags%}
            <select multiple class="filter-select-box-left" id="id_{{ field.name }}_from">
                {% if field.name in admin_class.readonly_fields %}
                    {% for obj_tag in  m2m_obj_tags%}
                        <option disabled="disabled" value="{{ obj_tag.id }}">{{ obj_tag }}</option>
                    {% endfor %}
                {% else %}
                    {% for obj_tag in  m2m_obj_tags%}
                        <option ondblclick="move_element(this,'id_{{ field.name }}_to','id_{{ field.name }}_from')" value="{{ obj_tag.id }}">{{ obj_tag }}</option>
                    {% endfor %}
                {% endif %}
            </select>
        </div>
        <div class="col-md-4">
            {% get_m2m_selected_tags form_obj field as select_tags%}
            <select tag="choose_list" multiple name="{{ field.name }}"class="filter-select-box-right" id="id_{{ field.name }}_to">
                {% if field.name in admin_class.readonly_fields %}
                    {% for obj_tag in  select_tags %}
                        <option disabled="disabled" value="{{ obj_tag.id }}">{{ obj_tag }}</option>
                    {% endfor %}
                {% else %}
                    {% for obj_tag in  select_tags %}
                        <option ondblclick="move_element(this,'id_{{ field.name }}_from','id_{{ field.name }}_to')" value="{{ obj_tag.id }}">{{ obj_tag }}</option>
                    {% endfor %}
                {% endif %}
            </select>
        </div>
        <span style="color:red">{{ field.errors }}</span>
    {% else %}
        {{ field }}
        <span style="color:red">{{ field.errors }}</span>
    {% endif %}

    二.后端数据校验

    思路:

      1.获取数据库中的值

      2.获取前端表单的值

           3.两者进行比较,如果不相等,就抛出异常,同时调用自定义的用户字段验证

     def default_clean(self):
    #self指的是前端提交的post表单对象和数据库查询的对象
    #所有的表单都适用,readonly字段的后端验证 for field in admin_class.readonly_fields:
    #根据admin_class中获取readonly_fields的字段 field_obj_db
    = getattr(self.instance,field) #获取其在数据库中的值      #多对多字段的readonly_field后端校验  if hasattr(field_obj_db,'select_related'):
    #如果readonly_field包含多对多的字段 m2m_objs
    = getattr(field_obj_db,'select_related')().select_related()#获取其在数据库中的对象 m2m_values = [i[0] for i in m2m_objs.values_list('id')]#获取其在多对多的对应的字段的id值 if set(m2m_values) != set([i.id for i in self.cleaned_data.get(field)]):
    #如果数据库中的值和前端传的值不相等,直接加入到异常列表中,展示到前端页面 self.add_error(
    '%s是只读字段,不能修改'%field) continue #获取前端表单中readonly_field的值 field_obj_front = self.cleaned_data.get(field) #前端readonly的值 if field_obj_db!=field_obj_front:
    #如果和数据库中的值不等,则抛出异常 error_list.append(ValidationError(
    '%s字段是只读字段,不允许更改'%field)) self.ValidationError = ValidationError
    #调用用户自定义验证 response
    = admin_class.default_form_validation(self)   
    #如果异常的列表中有值,打印到前端展示
    if response: error_list.append(response) if error_list: raise ValidationError(error_list)
    setattr(_model_form_class,'clean',default_clean) #设置到自动生成的类中

    三.在admin_class中进行自定义字段校验

    思路:

      1.在admin_class中的自定义单个字段校验以clean_+字段名开始,整体字段的校验写在default_form_validation方法中

           2.在from.py中的default_clean方法中集中调用进行验证

    整体校验

    def default_form_validation(self):
            '''整体表单字段的验证'''
            content = self.cleaned_data.get('content') #获取前端表单的值
            if len(content)<=15:
                return self.ValidationError('content字段的值不能少于15个字符')

    单个字段校验

        def clean_name(self):
    '''单个字段校验'''
    if not self.cleaned_data['name']: self.add_error('姓名不能为空')

    在form.py中的生成modelform的时候生成校验规则,如果不符合校验规则,则报错给前端页面

    自定义单个字段校验

    在__new__中,找到admin_class对应的名称,获取clean_+字段名的方法对象,同时将其绑定到类中

      if hasattr(admin_class,'clean_%s'%field_name):
            field_clean_func=getattr(admin_class,'clean_%s'%field_name)
            setattr(cls,'field_clean_func',field_clean_func)

    自定义整体校验

     self.ValidationError = ValidationError
     response= admin_class.default_form_validation(self) #此处传入的self即为views中传入的instance_obj对象和前端的request.POST表单对象

    readonly_field 前端展示:

    1.普通字段

    2.一对多字段

    3.多对对字段

  • 相关阅读:
    tensorflow2.0——动量,动态学习率,Dropout
    tensorflow2.0——过拟合优化regularization(简化参数结构,添加参数代价变量)
    tensorflow2.0——自定义全连接层实现并保存
    关于生成器的问题
    端午节大礼包(投票系统)
    写一个函数完成三次登陆功能,再写一个函数完成注册功能
    例题练习
    文件操作
    解决列表中增加字典覆盖之前相同key的字典
    字符串操作,列表,元组,字典操作
  • 原文地址:https://www.cnblogs.com/luhuajun/p/7890783.html
Copyright © 2011-2022 走看看