1、form按field自定义
官方文档上:https://docs.djangoproject.com/zh-hans/2.1/ref/forms/validation/写着可以用字段名
from django import forms
class ContactForm(forms.Form):
# Everything as before.
...
def clean_recipients(self):
data = self.cleaned_data['recipients']
if "fred@example.com" not in data:
raise forms.ValidationError("You have forgotten about Fred!")
# Always return a value to use as the new cleaned data, even if
# this method didn't change it.
return data
在kind_admin.py文件中Customer类中自定义clean_name函数来判断name不能为空:
def clean_name(self):
#获取请求的name值
name = self.cleaned_data["name"]
if not name:
#添加报错信息
self.add_error("name"," cannot be null")
在form.py文件中clean_name函数添加到form的clean_field函数中:
#判断名字不能为空
#判断admin_class里否有clean_name函数
if hasattr(admin_class, 'clean_%s'%field_name):
#获取clean_name函数
clean_names = getattr(admin_class,"clean_%s"%field_name)
#把clean_name函数添加到form的clean_field中
setattr(cls, 'clean_%s'%field_name, clean_names)
2、多选框readonly
在前端中判断表单字段是否在kind_admin.py文件的readonly_fields = ['qq','consultant','tags']中,多选的字段是tags
在后端返回的错误提示可以用
{{form_obj.errors}} 或者
{{filed_form.errors.as_text}}在前端获取
table_objs_change.html文件中:
<div class="col-sm-10">
{#<input type="email" id="inputEmail3" placeholder="{{filed_form}}">#}
{% if filed_form.name in admin_class.filter_horizontal%}
<div class="col-lg-5">
{% get_m2m_choose_data admin_class filed_form form_obj as m2m_obj_list%}
<select multiple class="filter-select-box" id="id_{{filed_form.name}}_from">
{% if filed_form.name in admin_class.readonly_fields%}
{% for m2m_obj in m2m_obj_list%}
<option value="{{m2m_obj.id}}" disabled>{{m2m_obj}}</option>
{% endfor %}
{% else %}
{% for m2m_obj in m2m_obj_list%}
<option ondblclick="MoveElementTo(this,'id_{{ filed_form.name }}_to','id_{{ filed_form.name }}_from')" value="{{m2m_obj.id}}">{{m2m_obj}}</option>
{% endfor %}
{% endif %}
</select>
</div>
<div class="col-md-1">
箭头
</div>
<div class="col-lg-5">
{% get_m2m_selected_obj filed_form form_obj as m2m_seleced_list %}
<select tag="chosen_list" multiple class="filter-select-box" id="id_{{filed_form.name}}_to" name="{{filed_form.name}}">
{% if filed_form.name in admin_class.readonly_fields%}
{% for m2m_selected_obj in m2m_seleced_list %}
<option value="{{m2m_selected_obj.id}}" disabled>{{m2m_selected_obj}}</option>
{% endfor %}
{% else %}
{% for m2m_selected_obj in m2m_seleced_list %}
<option ondblclick="MoveElementTo(this,'id_{{ filed_form.name }}_from','id_{{ filed_form.name }}_to')" value="{{m2m_selected_obj.id}}">{{m2m_selected_obj}}</option>
{% endfor %}
{% endif %}
</select>
</div>
因为tags是多对多的关系,所以要获取数据库中的数据和请求过来的数据是否相等需要做如下,可以先判断数据库里的值是否有“select_related”属性(多对多专有)
list_error=[] for field in admin_class.readonly_fields: #在表单可读在数据库里的数据 from_db_data = getattr(self.instance,field) #判断从数据库中取出的值是多对对的 if hasattr(from_db_data,"select_related"): #获取m2m多对多值的的对象 m2m_obj = getattr(from_db_data,"select_related")().select_related() print("m2m_obj",m2m_obj) #获取tags的值并切割出来 m2m_val = [i[0] for i in m2m_obj.values_list("id")] #强转数据为集合为了与下面请求的数据比较 set_m2m_val = set(m2m_val) print("set_m2m_val",set_m2m_val) #多对多页面请求的值values值 set_m2m_vals_from_frontend = set([i.id for i in self.cleaned_data.get(field)]) print("set_m2m_vals_from_frontend",set_m2m_vals_from_frontend) if set_m2m_val != set_m2m_vals_from_frontend: self.add_error(field,"readonly field") #这个就不执行下面语句了 continue