CRM 跳转到数据修改页面、动态生成model,form、增加新增页面——第21天
1、跳转到数据修改页面
1、1 新建一个table_objs_change.html文件,继承kindadmin/table_index.html页面
table_objs_change.html:
{% extends 'kindadmin/table_index.html'%} {% load tags %} {% block container %} change <form class="form-horizontal" method="post">{% csrf_token %} <div style="color: red">{{form_obj.errors}}</div> {% for filed_form in form_obj%} <div class="form-group"> <label class="col-sm-2 control-label" style="font-weight:normal"> {% if filed_form.field.required%} <b>{{filed_form.label}}</b> {% else %} {{filed_form.label}} {% endif %} </label> <div class="col-sm-10"> {#<input type="email" id="inputEmail3" placeholder="{{filed_form}}">#} {{filed_form}} </div> </div> {% endfor %} <div class="form-group"> <button type="submit" class="btn btn-success pull-right" >SAVE</button> </div> </form> {% endblock %}
1.2在urls文件中加上路由的url
url(r'^(\w+)/(\w+)/(\d+)/change/$',views.table_objs_change,name='table_objs_change'),
1.3 url是判断点击页面row=0的可以点击进入页面,在tag.py文件中:
@register.simple_tag def build_table_raw(obj,admin_class,request): """ :param obj: admin_class.model.objects.all(),在前端已经一个一个的类数据循环 :param admin_class: CustomerAdmin :return:对应字段的值 """ raw_ele = "" for index,column in enumerate(admin_class.list_display): #获取该类内指定字段的信息 field_obj = obj._meta.get_field(column) if field_obj.choices: #获取字段choices里的中文值 column_data = getattr(obj,"get_%s_display" %column)() else: column_data = getattr(obj,column) #print("type(column_date)类型:",column,type(column).__name__) if type(column_data).__name__ == 'datetime': column_data = column_data.strftime("%Y-%m-%d %H:%M:%S") if index==0: column_data = "<a href='{request_path}{colum_id}/change/'>{data}</a>".format(request_path=request.path, colum_id=obj.id, data=column_data) raw_ele += "<td>%s</td>" % column_data
1.4在view.py文件创建一个table_objs_change函数,返回table_objs_change.html页面
def table_objs_change(request,app_name,table_name,obj_id): """修改更新信息页面""" return render(request,"kindadmin/table_objs_change.html")
在url里面有几个值匹配,在view.py文件中的函数就得传几个函数变量不然后报错的
2、动态生成model,form
2、1 在kindadmin/forms.py 新建forms.py文件用来动态生成form,如下:
from django.forms import forms,ModelForm from PerfectCRM.Perfectcrm.crm import models def creat_model_form(request,admin_class): def __new__(cls,*args,**kwargs): #super(CustomerForm,self).__new__(*args,**kwargs) print("base fields",cls.base_fields) for field_name,field_obj in cls.base_fields.items(): print(field_name,dir(field_obj)) field_obj.widget.attrs['class'] = 'form-control' field_obj.widget.attrs['maxlength'] = getattr(field_obj,'max_length')if hasattr(field_obj,"max_length") else '' return ModelForm.__new__(cls) class Meta: model = admin_class.model fields = "__all__" attr = {"Meta":Meta} _model_form_class = type("DynamicModelForm",(ModelForm,),attr) return _model_form_class
from django.forms import forms,ModelForm from PerfectCRM.Perfectcrm.crm import models def creat_model_form(request,admin_class): class Meta: model = admin_class.model fields = "__all__" attr = {"Meta":Meta} _model_form_class = type("DynamicModelForm",(ModelForm,),attr) return _model_form_class #上面的creat_model_form函数相当于: #主要是因为type的关系: #type 第一个函数:类名 #type 第二个函数:当前需要继承的基类记住他是元组(a,) #type 第三个元素:类的成员,不管是函数还是类都可以 def creat_model_form(request,admin_class): class DynamicModelForm(ModelForm): class Meta: model = admin_class.model fields ="__all__"
return DynamicModelForm
2.2 在view.py文件引入自动生成的form,前端请求提交是用POST的请求方式在前端得加{% csrf_token %},点击进入更新页面是需要有之前新建的数据利用instance这个参数,前端如果后台更新报错,可以使用{{form_obj.errors}},在view.py文件的table_objs_change函数:
def table_objs_change(request,app_name,table_name,obj_id): """修改更新信息页面""" admin_class = kind_admin.enabled_admins[app_name][table_name] model_form_class = creat_model_form(request,admin_class) obj = admin_class.model.objects.get(id=obj_id) if request.method == "POST": form_obj = model_form_class(request.POST,instance=obj) #更新 #判断更新的值是否合法 if form_obj.is_valid(): form_obj.save() else: form_obj = model_form_class(instance=obj) return render(request,"kindadmin/table_objs_change.html",{"form_obj":form_obj})
在前端可以判断如果字段是必填就加粗,其他的页面格式可以自己调调:
{% for filed_form in form_obj%} <div class="form-group"> <label class="col-sm-2 control-label" style="font-weight:normal"> {% if filed_form.field.required%} <b>{{filed_form.label}}</b> {% else %} {{filed_form.label}} {% endif %} </label> <div class="col-sm-10"> {#<input type="email" id="inputEmail3" placeholder="{{filed_form}}">#} {{filed_form}} </div>
3、增加新增数据页面
3、1 新建table_objs_add.html页面,继承table_objs_change.html页面,,在table_objs页面一个add ,点击这个add会进入table_objs_add.html页面
<a class="pull-right" href="{{request.path}}add/">Add</a> #request.path表示当前路径
3、2 增加urls文件中的url:
url(r'^(\w+)/(\w+)/add/$', views.table_objs_add, name='table_objs_add'),
3.3 在view.py文件中增加一个table_objs_add函数,新增就都是全新的不需要instance这个,新增成功之后需要重新返回到http://127.0.0.1:8000/kind_admin/crm/customer/页面
所以需要redirect重定向,request.path是当前没有参数的路径:
from django.shortcuts import render,redirect
def table_objs_add(request,app_name,table_name): """增加信息页面""" admin_class = kind_admin.enabled_admins[app_name][table_name] model_form_class = creat_model_form(request, admin_class) if request.method == 'POST': form_obj = model_form_class(request.POST) #新增 if form_obj.is_valid(): form_obj.save() return redirect(request.path.replace("/add/","/")) else: form_obj = model_form_class() return render(request,"kindadmin/table_objs_add.html",{"form_obj":form_obj})
3.4为了是页面一开始就是按某一个字段倒序显示:
def table_filter(request,admin_class): """进行条件过滤并返回过滤后的数据""" filter_conditions = {} for k,v in request.GET.items(): kitem =['page','o','_q'] if k in kitem: continue if v: filter_conditions[k]=v print("filter_conditions:",filter_conditions) print("admin_class.model.objects.filter(**filter_conditions)",admin_class.model.objects.filter(**filter_conditions)) return admin_class.model.objects.filter(**filter_conditions).order_by("-%s"% admin_class.ordering if admin_class.ordering else "-id") \ ,filter_conditions