美文网首页Python Web开发学习
【CRM客户关系管理】16. 只读字段readonly_fiel

【CRM客户关系管理】16. 只读字段readonly_fiel

作者: 吾星喵 | 来源:发表于2018-12-04 15:13 被阅读2次

    个人博客,欢迎查看: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']字段,则就会显示联系方式客户状态表单

    image.png

    模板标签显示只读字段值

    创建模板标签,用于显示这些只读字段的值

    修改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 }} - 编辑 &nbsp;&nbsp; {{ 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 }} - 编辑 &nbsp;&nbsp; {{ 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 %}
    

    现在增加数据和修改数据都可以正常使用了。

    相关文章

      网友评论

        本文标题:【CRM客户关系管理】16. 只读字段readonly_fiel

        本文链接:https://www.haomeiwen.com/subject/sznmcqtx.html