您的当前位置:首页正文

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

来源:花图问答

只读字段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 %}
image.png

现在修改没有问题了,但是在添加的时候报错

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 %}

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