Django项目:CRM(客户关系管理系统)--69--59PerfectCRM实现king_admin行内编辑
#base_admin.py # ————————24PerfectCRM实现King_admin自定义操作数据————————
from django.shortcuts import render,redirect
# ————————24PerfectCRM实现King_admin自定义操作数据———————— # ————————04PerfectCRM实现King_admin注册功能———————— #Django admin 注册功能的形式
# sites = {
# 'crm':{
# 'customers':CustomerAdmin,
# 'customerfollowup':CustomerFollowUPAdmin,
# }
# } class AdminRegisterException(Exception): #自定义异常
def __init__(self,msg):
self.message = msg class BaseAdmin(object):#自定义方法
list_display = () #显示的字段(不能包含ManyToManyField) # ————————11PerfectCRM实现King_admin分页显示条数————————
list_per_page = 10 # 默认分页条数10
# ————————11PerfectCRM实现King_admin分页显示条数———————— # ————————15PerfectCRM实现King_admin多条件过滤————————
list_filter = () # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
# ————————15PerfectCRM实现King_admin多条件过滤———————— # ————————18PerfectCRM实现King_admin搜索关键字————————
search_fields = () #搜索(不能包含CharField)(注意加 逗号 , )
# ————————18PerfectCRM实现King_admin搜索关键字———————— # ————————26PerfectCRM实现King_admin自定义排序————————
ordering = None #自定义排序
# ————————26PerfectCRM实现King_admin自定义排序———————— # ————————27PerfectCRM实现King_admin编辑复选框————————
filter_horizontal = []#复选框
# ————————27PerfectCRM实现King_admin编辑复选框———————— # ————————33PerfectCRM实现King_admin编辑整张表限制————————
readonly_table=False#默认表单不锁定
# ————————33PerfectCRM实现King_admin编辑整张表限制———————— # ————————36PerfectCRM实现King_admin密码修改————————
modelform_exclude_fields=[]#排除验证字段
# ————————36PerfectCRM实现King_admin密码修改———————— # ————————55PerfectCRM实现CRM客户报名状态颜色变化————————
colored_fields = {}
# ————————55PerfectCRM实现CRM客户报名状态颜色变化———————— # ————————59PerfectCRM实现king_admin行内编辑————————
list_editable = []#可编辑
# ————————59PerfectCRM实现king_admin行内编辑———————— # ————————24PerfectCRM实现King_admin自定义操作数据————————
actions = []#自定功能 default_actions = ["delete_selected",] #默认删除的函数
#默认删除的函数
def delete_selected(self,request,queryset):
# from django.shortcuts import render, redirect
print("goint to delete ",queryset)
app_name=self.model._meta.app_label#app名
model_name=self.model._meta.model_name#表名
objs=queryset#类对象
action=request._admin_action
print(action,'<-------action') # ————————33PerfectCRM实现King_admin编辑整张表限制————————
if self.readonly_table:
errors={'锁定的表单':'当前表单已经锁定,不可进行批量删除操作!'}
else:
errors={}
# ————————33PerfectCRM实现King_admin编辑整张表限制———————— if request.POST.get('delete_confirm')=='yes': #{#table_delete.html#} # ————————33PerfectCRM实现King_admin编辑整张表限制————————
if not self.readonly_table:
# ————————33PerfectCRM实现King_admin编辑整张表限制————————
queryset.delete()
return redirect('/king_admin/%s/%s/'%(app_name,model_name))
else:
return redirect('/king_admin/%s/%s/' % (app_name, model_name))
selected_ids=','.join([str(i.id) for i in queryset])
print(selected_ids,'<---selected_ids')
objs=queryset
return render(request,"king_admin/table_delete.html", locals()) #返回删除页
delete_selected.short_description = "默认批量删除"
# ————————24PerfectCRM实现King_admin自定义操作数据———————— # ————————28PerfectCRM实现King_admin编辑限制————————
readonly_fields = [] # 不可修改 # ————————29PerfectCRM实现King_admin编辑自定义限制————————
#默认表单验证 全部 可重写
def default_form_validation(self,request):
#用户可以在此进行自定义的表单验证,相当于django form 的clean方法
'''默认表单验证 == django form 的clean方法'''
pass
# ————————29PerfectCRM实现King_admin编辑自定义限制————————
# ————————28PerfectCRM实现King_admin编辑限制———————— # ————————05PerfectCRM实现King_admin注册功能获取内存————————
class AdminSite(object):
def __init__(self):
self.registered_sites = {} #传到views 里调用
def register(self,model,admin_class=None): #默认值None 使用 BaseAdmin
app_name = model._meta.app_label#用内置方法获取 APP名字 (crm)
model_name = model._meta.model_name#用内置方法获取 表名 (Customer)
if app_name not in self.registered_sites:
self.registered_sites[app_name] = {} #创建 crm={}
if model_name in self.registered_sites[app_name]:
raise AdminRegisterException("app [%s] model [%s] has already registered!异常"
%(app_name,model_name))#自定义异常,
if not admin_class:
admin_class = BaseAdmin #默认值None 使用 BaseAdmin
# self.registered_sites[app_name][model_name] = admin_class #注册APP
# site = AdminSite() # 实例化类 单例模式 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
#registered_sites {'crm': {'customer': <class 'crm.kingadmin.CustomerAdmin'>, 'courserecord': <class 'kingadmin.base_admin.BaseAdmin'>}}
#把类名放到class的对象里,然后通过class的对象传到前端
# admin_class.model = model
# self.registered_sites[app_name][model_name] = admin_class #注册APP
#
# site = AdminSite() #实例化类 单例模式
# ————————05PerfectCRM实现King_admin注册功能获取内存———————— # ————————06PerfectCRM实现King_admin注册功能获取内存优化处理————————
#没有实例化会使用同一个内存地址
admin_obj = admin_class() #先实例化
admin_obj.model = model #参数赋值给实例
self.registered_sites[app_name][model_name] = admin_obj#注册APP
#实例化后,调用会使用不同的内存地址 site = AdminSite() #实例化类 单例模式
# ————————06PerfectCRM实现King_admin注册功能获取内存优化处理———————— # registered_sites={}
# def register(model,admin_class=None): #默认值None 使用 BaseAdmin
# app_name = model._meta.app_label#用内置方法获取 APP名字 (crm)
# model_name = model._meta.model_name#用内置方法获取 表名 (Customer)
# if app_name not in registered_sites:
# registered_sites[app_name] = {} #创建 crm={}
# if model_name in registered_sites[app_name]:
# raise AdminRegisterException("app [%s] model [%s] has already registered!异常"
# %(app_name,model_name))#自定义异常
# if not admin_class:
# admin_class = BaseAdmin #默认值None 使用class BaseAdmin
# registered_sites[app_name][model_name] = admin_class #注册APP # ————————05PerfectCRM实现King_admin注册功能获取内存———————— # ————————04PerfectCRM实现King_admin注册功能————————
#base_admin.py
# views # ————————02PerfectCRM创建ADMIN页面————————
from django.shortcuts import render # ————————04PerfectCRM实现King_admin注册功能————————
# from django import conf #配置文件
# print("dj conf:",conf) #配置文件
# print("dj conf:",conf.settings)#配置文件.设置
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————04PerfectCRM实现King_admin注册功能————————
from king_admin import app_config # 自动调用 动态加载类和函数
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————04PerfectCRM实现King_admin注册功能————————
# from king_admin.base_admin import registered_sites # registered_sites={}
from king_admin import base_admin
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————11PerfectCRM实现King_admin基本分页————————
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 分页功能
# ————————11PerfectCRM实现King_admin基本分页———————— # ————————46PerfectCRM实现登陆后页面才能访问————————
from django.contrib.auth.decorators import login_required # ————————46PerfectCRM实现登陆后页面才能访问———————— def app_index(request):
# ————————04PerfectCRM实现King_admin注册功能————————
# for app in conf.settings.INSTALLED_APPS:
# print(app)#循环打印 配置文件.设置.安装应用程序#.Perfectcustomer\settings里的INSTALLED_APPS列表
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————04PerfectCRM实现King_admin注册功能————————
# return render(request, 'king_admin/app_index.html')
# print("registered_sites",registered_sites)
# return render(request, 'king_admin/app_index.html')
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————04PerfectCRM实现King_admin注册功能————————
# print("registered_sites", base_admin.registered_sites)
# return render(request, 'king_admin/app_index.html')
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————05PerfectCRM实现King_admin注册功能获取内存————————
print("registered_sites", base_admin.site.registered_sites)
return render(request, 'king_admin/app_index.html', {"site": base_admin.site}) # ————————05PerfectCRM实现King_admin注册功能获取内存———————— # ————————02PerfectCRM创建ADMIN页面———————— # ————————13PerfectCRM实现King_admin分页页数————————
# 处理def table_data_list(request,app_name,model_name):里的内容,
def filter_querysets(request, queryset):
condtions = {} # 定义一个字典用来存过滤的条件
for k, v in request.GET.items(): # 不需要空的,判断是否为空
# ————————18PerfectCRM实现King_admin搜索关键字————————
# ————————17PerfectCRM实现King_admin单列排序————————
# if k=="page":continue##kingadmin分页功能 # if k=="page":continue##kingadmin分页功能 #写法一
# elif k=="_o":continue##kingadmin排序功能 <a href="?_o={{ column }}">{{ column }}</a> # if k in ("page","_o") :continue #kingadmin分页功能 #kingadmin排序功能 #写法二 # if k == "page"or k == "_o": #保留的分页关键字 和 排序关键字 #写法三
# continue #continue是结束单次循环
# ————————17PerfectCRM实现King_admin单列排序————————
if k in ("page", "_o", "_q"): continue # kingadmin分页,排序,搜索#判断标签是否存在 自定义的名称
# ————————18PerfectCRM实现King_admin搜索关键字———————— # ————————15PerfectCRM实现King_admin多条件过滤————————
if v:
condtions[k] = v # 进行配对字典
# ————————15PerfectCRM实现King_admin多条件过滤————————
query_res = queryset.filter(**condtions) return query_res, condtions # ————————13PerfectCRM实现King_admin分页页数———————— # ————————59PerfectCRM实现king_admin行内编辑————————
from king_admin import form def batch_update(request, editable_data, admin_obj):
"""table objects batch update , for list_editable feature"""
errors = [] # 错误信息
for row_data in editable_data:
obj_id = row_data.get('id') # 获取这行ID号
try:
if obj_id:
print("如果有ID编辑数据:", row_data, list(row_data.keys()))
obj = admin_obj.model.objects.get(id=obj_id) # 获取编辑的ID
model_form = form.create_form(admin_obj.model, list(row_data.keys()),
admin_obj, request=request, partial_update=True) # 进行数据验证处理
form_obj = model_form(instance=obj, data=row_data) # 编辑的ID #验证的内容
if form_obj.is_valid(): # 验证通过
form_obj.save() # 保存新内容
print('保存。。。。') else:
print("可编辑列表形式", row_data, form_obj.errors) errors.append([form_obj.errors, obj]) # 添加错误信息 # for column in row_data:
# if column != "id":#id no need change
# #print("-----column",column,row_data[column],type(row_data[column]))
# if row_data[column] in ('True','False'):
# if obj._meta.get_field(column).get_internal_type() == "BooleanField":
# setattr(obj, column, eval(row_data[column]))
# #print("setting column [%s] to [%s]" %(column,row_data[column]), eval(row_data[column]))
# else:
# setattr(obj, column, row_data[column])
# else:
# setattr(obj,column,row_data[column])
#
# obj.save() # except Exception as e:
except KeyboardInterrupt as e:
return False, [e, obj]
if errors:
return False, errors
return True, [] # ————————59PerfectCRM实现king_admin行内编辑———————— # ————————08PerfectCRM实现King_admin显示注册表的字段表头————————
@login_required # 登陆后页面才能访问
def table_data_list(request, app_name, model_name):
# 通过2个参数到base_admin里获取class AdminRegisterException(Exception): 的对象
admin_obj = base_admin.site.registered_sites[app_name][model_name] # base_admin # ————————24PerfectCRM实现King_admin自定义操作数据————————
if request.method == "POST": # 批量操作
action = request.POST.get("action_select") # 要调用的自定制功能函数
selected_ids = request.POST.get("selected_ids") # 前端提交的数据
print(selected_ids, type(selected_ids), "selected_ids-----")
# if type(selected_ids)!='str':
# selected_ids = json.loads(selected_ids)#进行转换数据
print(selected_ids, type(action), action, "selected_ids==========")
# print("action:",selected_ids,action)
# ————————59PerfectCRM实现king_admin行内编辑————————
import json
editable_data = request.POST.get("editable_data") # 获取前端可编辑的数据
print('编辑数据:', editable_data)
if editable_data: # for list editable
editable_data = json.loads(editable_data) # 进行转换数据
# print("editable",editable_data)
res_state, errors = batch_update(request, editable_data, admin_obj) # 进行部分更新操作
else:
# ————————59PerfectCRM实现king_admin行内编辑————————
if selected_ids:
# selected_ids = json.loads(selected_ids)#进行转换数据
selected_objs = admin_obj.model.objects.filter(id__in=selected_ids.split(',')) # 返回之前所选中的条件
else:
raise KeyError('错误,没有选择对象!') if hasattr(admin_obj, action):
action_func = getattr(admin_obj, action) # 如果admin_obj 对象中有属性action 则打印self.action的值,否则打印'not find'
request._admin_action = action # 添加action内容
print(request._admin_action, action, '<--------')
return action_func(request, selected_objs)
# ————————24PerfectCRM实现King_admin自定义操作数据———————— # ————————09PerfectCRM实现King_admin显示注册表的内容————————
admin_obj.querysets = admin_obj.model.objects.all() # 取数据 传到 前端
# ————————09PerfectCRM实现King_admin显示注册表的内容———————— # ————————11PerfectCRM实现King_admin分页显示条数————————
# from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 分页功能#放在顶上导入
obj_list = admin_obj.model.objects.all() # 取数据 传到 前端 #base_admin #获取传过来的所有对象 # ————————13PerfectCRM实现King_admin分页页数————————
queryset, condtions = filter_querysets(request, obj_list) # base_admin # 调用条件过滤
# ————————13PerfectCRM实现King_admin分页页数———————— # ————————18PerfectCRM实现King_admin搜索关键字————————
queryset = get_queryset_search_result(request, queryset, admin_obj) ##搜索后
# ————————18PerfectCRM实现King_admin搜索关键字———————— # ————————26PerfectCRM实现King_admin自定义排序————————
sorted_queryset = get_orderby(request, queryset, admin_obj) # 排序后的结果
# ————————17PerfectCRM实现King_admin单列排序————————
# sorted_queryset = get_orderby(request, queryset) #排序后的结果
# ————————15PerfectCRM实现King_admin多条件过滤————————
# paginator = Paginator(obj_list,admin_obj.list_per_page) #kingadmin里class CustomerAdmin(BaseAdmin):
# paginator = Paginator(queryset, admin_obj.list_per_page)
# ————————15PerfectCRM实现King_admin多条件过滤————————
paginator = Paginator(sorted_queryset, admin_obj.list_per_page)
# ————————17PerfectCRM实现King_admin单列排序————————
# ————————26PerfectCRM实现King_admin自定义排序———————— page = request.GET.get('page')
try:
objs = paginator.page(page) # 当前的页面的数据
except PageNotAnInteger:
# 如果页面不是一个整数,交付第一页。
objs = paginator.page(1)
except EmptyPage:
# 如果页面的范围(例如9999),交付最后一页的搜索结果。
objs = paginator.page(paginator.num_pages)
admin_obj.querysets = objs # base_admin # ————————13PerfectCRM实现King_admin分页页数————————
admin_obj.filter_condtions = condtions # base_admin
# ————————13PerfectCRM实现King_admin分页页数———————— # ————————11PerfectCRM实现King_admin分页显示条数———————— return render(request, "king_admin/table_data_list.html", locals()) # ————————08PerfectCRM实现King_admin显示注册表的字段表头———————— # ————————17PerfectCRM实现King_admin单列排序————————
# def get_orderby(request,queryset):
# order_by_key = request.GET.get("_o") #获取URL里有没有("_o") <a href="?_o={{ column }}">{{ column }}</a>
# #页面刚开始没有这个值
# if order_by_key != None: #有("_o")这个值 就进行排序
# query_res = queryset.order_by(order_by_key)
# else: #没有就不排序,直接返回
# query_res = queryset
# return query_res #排序时会错 # orderby_key = request.GET.get("_o")
# if orderby_key:
# return queryset.order_by(orderby_key)
# return queryset # 在table_data_list添加
# def table_data_list(request,app_name,model_name): #详细列表
# sorted_queryset = get_orderby(request, queryset)
# 在filter_querysets添加
# if k == "page"or k == "_o": #保留的分页关键字 和 排序关键字
# ————————17PerfectCRM实现King_admin单列排序———————— # ————————26PerfectCRM实现King_admin自定义排序————————
def get_orderby(request, queryset, admin_obj):
orderby_key = request.GET.get("_o")
# order_by_key1=order_by_key.strip()
if orderby_key: # 有获取到字段
query_res = queryset.order_by(orderby_key.strip()) # .strip()默认删除空白符(包括'\n', '\r', '\t', ' ')
else:
if admin_obj.ordering: # 查看kingadmin‘有没有 ordering = '-qq' # 自定义排序
query_res = queryset.order_by("%s" % admin_obj.ordering)
else:
query_res = queryset.order_by('-id') # 默认倒序
return query_res # 在table_data_list添加
# def table_data_list(request,app_name,model_name): #详细列表
# sorted_queryset = get_orderby(request, queryset, admin_obj) # 排序后的结果
# ————————26PerfectCRM实现King_admin自定义排序———————— # ————————18PerfectCRM实现King_admin搜索关键字————————
from django.db.models import Q def get_queryset_search_result(request, queryset, admin_obj):
search_key = request.GET.get("_q", "") # 取定义名,默认为空
q_obj = Q() # 多条件搜索 #from django.db.models import Q
q_obj.connector = "OR" # or/或 条件
for column in admin_obj.search_fields: # 搜索目标crm/kingadmin里class CustomerAdmin(BaseAdmin):search_fields = ('name','qq',)
q_obj.children.append(("%s__contains" % column, search_key)) # 运态添加多个条件
res = queryset.filter(q_obj) # 对数据库进行条件搜索
return res # 返回结果 # 在table_data_list添加
# def table_data_list(request,app_name,model_name): #详细列表
# queryset = get_queryset_search_result(request,queryset,admin_obj)
# ————————18PerfectCRM实现King_admin搜索关键字———————— # ————————19PerfectCRM实现King_admin数据修改————————
from king_admin import forms # 修改内容
# def table_change(request,app_name,model_name):
# obj_form = forms.CustomerModelForm() #创建一个空表单
# return render(request,"kingadmin/table_change.html",locals())
@login_required # 登陆后页面才能访问
def table_change(request, app_name, model_name, obj_id):
admin_obj = base_admin.site.registered_sites[app_name][model_name] # 获取表对象
# kingadmin/forms.py里def CreateModelForm(request,admin_obj):
model_form = forms.CreateModelForm(request, admin_obj=admin_obj) ##modelform 生成表单 加验证
# obj_form = model_form() # 表单
obj = admin_obj.model.objects.get(id=obj_id) # 根据ID获取数据记录 # ————————28PerfectCRM实现King_admin编辑限制————————
# ————————20PerfectCRM实现King_admin数据修改美化————————
# #面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
# obj_form = model_form(instance=obj) # 数据传入表单 if request.method == "GET": # 如果是 GET 表示 是添加记录
obj_form = model_form(instance=obj) # 数据传入表单
elif request.method == "POST": # 如果是 POST 表示 是修改后的数据
obj_form = model_form(instance=obj, data=request.POST) # 更新数据
if obj_form.is_valid():
obj_form.save()
# ————————20PerfectCRM实现King_admin数据修改美化————————
# ————————28PerfectCRM实现King_admin编辑限制———————— return render(request, "king_admin/table_change.html", locals()) # ————————19PerfectCRM实现King_admin数据修改———————— # ————————21PerfectCRM实现King_admin查看页面美化————————
# 单个具体app页面
@login_required # 登陆后页面才能访问
def table_index(request, app_name):
bases = base_admin.site.registered_sites[app_name] # 取出对应app对象
return render(request, 'king_admin/table_index.html', {"site": bases, 'app_name': app_name}) # ————————21PerfectCRM实现King_admin查看页面美化———————— # ————————22PerfectCRM实现King_admin数据添加————————
from django.shortcuts import redirect # kingadmin添加内容 @login_required # 登陆后页面才能访问
def table_add(request, app_name, model_name):
admin_obj = base_admin.site.registered_sites[app_name][model_name] # 获取表对象
# ————————32PerfectCRM实现King_admin添加不进行限制————————
admin_obj.is_add_form = True # 表示为新增表单
# ————————32PerfectCRM实现King_admin添加不进行限制————————
model_form = forms.CreateModelForm(request, admin_obj=admin_obj) ##modelform 生成表单 加验证
if request.method == "GET":
obj_form = model_form() # 跳转过来的为空
elif request.method == "POST":
obj_form = model_form(data=request.POST) # 创建数据 # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
password = request.POST.get('password') # 取前端输入的密码
email = request.POST.get('email') # 取前端输入的邮箱
# ————————37PerfectCRM实现King_admin添加用户时密码加密———————— if obj_form.is_valid():
# ————————32PerfectCRM实现King_admin添加不进行限制————————
# obj_form.save()
try:
obj_form.save() # 表单验证通过保存
except Exception as e:
return redirect("/king_admin/%s/%s/" % (app_name, model_name)) # 转到之前的页面
# ————————32PerfectCRM实现King_admin添加不进行限制————————
if not obj_form.errors: # 没有错误返回原来的页面 # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
if email:
obj = admin_obj.model.objects.filter(email=email).first() # 对象
obj.set_password(password) # 加密
try:
obj.save() # 表单验证通过保存
except Exception as e:
return redirect("/king_admin/%s/%s/" % (app_name, model_name))
# ————————37PerfectCRM实现King_admin添加用户时密码加密———————— # from django.shortcuts import redirect
return redirect("/king_admin/%s/%s/" % (app_name, model_name))
return render(request, "king_admin/table_add.html", locals()) # ————————22PerfectCRM实现King_admin数据添加———————— # ————————23PerfectCRM实现King_admin数据删除————————
@login_required # 登陆后页面才能访问
def table_delete(request, app_name, model_name, obj_id):
admin_obj = base_admin.site.registered_sites[app_name][model_name] # 表类
objs=admin_obj.model.objects.filter(id=obj_id)#类的对象 # ————————33PerfectCRM实现King_admin编辑整张表限制————————
# if request.method=='POST':
# objs.delete()#删除
# return redirect("/king_admin/%s/%s/" % (app_name,model_name))#转到列表页面 app_name=app_name
if admin_obj.readonly_table:
errors={'锁定的表单':'该表单:<%s>,已经锁定,不能删除当前记录!'%model_name}
else:
errors={}
if request.method=='POST':
if not admin_obj.readonly_table:
objs.delete()#删除
return redirect("/king_admin/%s/%s/" % (app_name,model_name))#转到列表页面
# ————————33PerfectCRM实现King_admin编辑整张表限制———————— return render(request, "king_admin/table_delete.html", locals()) # locals 返回一个包含当前范围的局部变量字典。 # ————————23PerfectCRM实现King_admin数据删除———————— # ————————36PerfectCRM实现King_admin密码修改————————
# 密码修改
@login_required # 登陆后页面才能访问
def password_reset(request, app_name, model_name, obj_id):
admin_obj = base_admin.site.registered_sites[app_name][model_name] # 表类
model_form = forms.CreateModelForm(request, admin_obj=admin_obj) # modelform 生成表单 加验证
obj = admin_obj.model.objects.get(id=obj_id) # 类表的对象
errors = {} # 错误提示
if request.method == 'POST':
_password1 = request.POST.get('password1') # 获取页面输入的值
_password2 = request.POST.get('password2') # 获取页面输入的值
if _password1 == _password2:
if len(_password1) > 5:
obj.set_password(_password1) # 继承Django方法 #加密
obj.save() # 保存
return redirect(request.path.rstrip('password/') + ('/change/')) # 替换URL名
else:
errors['password_too_short'] = '必须不少于6字符'
else:
errors['invalid_password'] = '两次输入的密码不一样' # 密码不一致 return render(request, "king_admin/password_reset.html", locals()) # locals 返回一个包含当前范围的局部变量字典。 # ————————36PerfectCRM实现King_admin密码修改———————— # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
def password_add(request, app_name, model_name):
return redirect("/king_admin/%s/%s/add/" % (app_name, model_name)) # 转到添加页面
# ————————37PerfectCRM实现King_admin添加用户时密码加密————————
# views
# form.py
# ————————59PerfectCRM实现king_admin行内编辑————————
from django import forms
from django.forms import ModelForm
def __new__(cls, *args, **kwargs):
# super(CustomerForm, self).__new__(*args, **kwargs)
# self.fields['customer_note'].widget.attrs['class'] = 'form-control'
#disabled_fields = ['qq', 'consultant']
for field_name in cls.base_fields:
field = cls.base_fields[field_name]
#print("field repr",field_name,field.__repr__())
attr_dic = {'placeholder': field.help_text} #占位符: 帮助文本
if 'BooleanField' not in field.__repr__(): #布尔字段 不在 #__repr__()返回一个对象的 string 格式
attr_dic.update({'class': 'form-control'}) # 更新
#print("-->field",field)
if 'ModelChoiceField' in field.__repr__(): #模型选择字段 在 #__repr__()返回一个对象的 string 格式
attr_dic.update({'data-tag':field_name}) # 更新 #数据标签
# if 'DateTimeField' in field.__repr__():
# attr_dic.update({'placeholder': field_name})
if cls.Meta.form_create is False: #表单创建 #是假
if field_name in cls.Meta.admin.readonly_fields: #只读的字段
attr_dic['disabled'] = True #禁用
#print('----read only:',field_name)
field.widget.attrs.update(attr_dic) # 更新
#for validators
if hasattr(cls.Meta.model,"clean_%s" % field_name): #hasattr() 函数用于判断对象是否包含对应的属性。
clean_field_func = getattr(cls.Meta.model,"clean_%s" % field_name) #getattr() 函数用于返回一个对象属性值。
setattr(cls,"clean_%s" % field_name,clean_field_func) #setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。
else:
if hasattr(cls.Meta.model, "clean2"): #clean2 is kingadmin's own clean method
clean_func = getattr(cls.Meta.model, "clean") #getattr() 函数用于返回一个对象属性值。
setattr(cls, "clean" , clean_func) #setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。
else:# use default clean method
setattr(cls, "clean", default_clean) #setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。
return ModelForm.__new__(cls) def default_clean(self): #clear()方法用于清空(或删除)字典中的所有数据项。
'''form defautl clean method'''
# print("\033[41;1mrun form defautl clean method...\033[0m",dir(self))
# print(self.Meta.admin.readonly_fields)
print("默认删除方法:",self.cleaned_data)
# print("validataion errors:",self.errors)
if self.Meta.admin.readonly_table is True:
raise forms.ValidationError(("这是一个只读的表"))
if self.errors:
raise forms.ValidationError(("请补交之前修复错误。."))
if self.instance.id is not None :#意味着这是一个改变形式,应该检查只读的字段
for field in self.Meta.admin.readonly_fields: #循环 readonly_fields 不可修改字段
old_field_val = getattr(self.instance,field) #getattr() 函数用于返回一个对象属性值。
form_val = self.cleaned_data.get(field)
print("提出不同的比较:",old_field_val,form_val)
if old_field_val != form_val: #如果旧字段和新字段不相等
if self.Meta.partial_update: #f可编辑的功能列表,只做部分检查
if field not in self.cleaned_data: # 如果字段 不在 清理数据理
#因为list_editable成生form时只生成了指定的几个字段,所以如果readonly_field里的字段不在,list_ediatble数据里,那也不检查了
continue #continue 语句跳出本次循环 self.add_error(field,"Readonly Field: field should be '{value}' ,not '{new_value}' ".\
format(**{'value':old_field_val,'new_value':form_val})) def create_form(model,fields,admin_obj,form_create=False,**kwargs):
class Meta:
pass
setattr(Meta,'model',model) # 如果类自定义了__setattr__方法,当通过实例获取属性尝试赋值时,就会调用__setattr__。常规的对实例属性赋值,被赋值的属性和值会存入实例属性字典__dict__中。
setattr(Meta,'fields',fields)
setattr(Meta,'admin',admin_obj)
setattr(Meta,'form_create',form_create) #表单创建
setattr(Meta,'partial_update',kwargs.get("partial_update")) #f可编辑的功能列表,只做部分检查 attrs = {'Meta':Meta}
name = 'DynamicModelForm' #动态模型的形式
baseclasess = (ModelForm,) #模型形式
model_form = type(name, baseclasess,attrs) #type属性类型
setattr(model_form,'__new__',__new__) # 如果类自定义了__setattr__方法,当通过实例获取属性尝试赋值时,就会调用__setattr__。常规的对实例属性赋值,被赋值的属性和值会存入实例属性字典__dict__中。 if kwargs.get("request"): #对表单验证器
setattr(model_form,'_request',kwargs.get("request")) #将给定对象命名属性设置为指定的值。
#print(model_form)
return model_form
# ————————59PerfectCRM实现king_admin行内编辑————————
# form.py
#kingadmin_tags.py # ————————06PerfectCRM实现King_admin注册功能获取内存优化处理———————— # # 因为前端禁止使用下划线开头(_meta.verbose_name ),所以通过后端处理后返回前端。
# from django import template #模板
# register = template.Library() #模板库
#
# @register.simple_tag #Django中利用filter与simple_tag为前端自定义函数的实现方法
# def get_app_name(model_obj):
#
# # ————————06PerfectCRM实现King_admin注册功能获取内存优化处理————————
# # return model_obj._meta.verbose_name_plural
# '''
# #判断 数据库 里如果有 verbose_name 或者 verbose_name_plural 就 调用 如果都没有 就使用默认的(英文)
# class Meta:
# verbose_name = "04客户信息表" #在 Django Admin 里 表名显示中文 但是会加s
# verbose_name_plural = "04客户信息表" #在 Django Admin 里 表名显示中文 不会加s
# '''
# model_name = model_obj._meta.verbose_name_plural if model_obj._meta.verbose_name else model_obj._meta.verbose_name_plural
# if not model_name:
# model_name = model_obj._meta.model_name
#
# return model_name
# ————————06PerfectCRM实现King_admin注册功能获取内存优化处理———————— # ————————06PerfectCRM实现King_admin注册功能获取内存优化处理———————— # ————————07PerfectCRM实现King_admin显示注册的表————————
#因为前端禁止使用下划线开头(_meta.verbose_name ),所以通过后端处理后返回前端。
from django import template #模板
register = template.Library() #模板库 @register.simple_tag #Django中利用filter与simple_tag为前端自定义函数的实现方法
def get_model_verbose_name(model_obj):
'''
#判断 数据库 里如果有 verbose_name 或者 verbose_name_plural 就 调用 如果都没有 就使用默认的(英文)
class Meta:
verbose_name = "04客户信息表" #在 Django Admin 里 表名显示中文 但是会加s
verbose_name_plural = "04客户信息表" #在 Django Admin 里 表名显示中文 不会加s
'''
model_name = model_obj._meta.verbose_name_plural if model_obj._meta.verbose_name else model_obj._meta.verbose_name_plural
if not model_name:
model_name = model_obj._meta.model_name
return model_name @register.simple_tag
def get_model_name(model_obj):
return model_obj._meta.model_name
@register.simple_tag
def get_app_name(model_obj):
return model_obj._meta.app_label
# ————————07PerfectCRM实现King_admin显示注册的表———————— # # ————————09PerfectCRM实现King_admin显示注册表的内容————————
# from django.utils.safestring import mark_safe #使用mark_safe函数标记后,django将不再对该函数的内容进行转义
# @register.simple_tag
# def build_table_row(admin_obj,obj):#通过kingadmin_tags在后台处理 再传到前端
# row_ele = "" #为了生成一整行返回前端
# if admin_obj.list_display:#如果不为空,有在crm/kingadmin.py注册site.register(models.Customer,CustomerAdmin)
#
# # ————————19PerfectCRM实现King_admin数据修改————————
# #循环所有 要显示 的字符串 进行反射 展示 字段
# # for column in admin_obj.list_display: #循环base_admin里class BaseAdmin下list_display = ()
# for index, column in enumerate(admin_obj.list_display): # 转为列表取 下标 , 字段名
# # ————————19PerfectCRM实现King_admin数据修改————————
#
# column_obj = obj._meta.get_field(column)#遍历获取 传进的参数对象
# if column_obj.choices:#判断如果字段有choices属性
# #获取choices的字符串(外健)
# get_column_data = getattr(obj,"get_%s_display" % column) #反射,传进的参数对象,拼接字段
# column_data = get_column_data()#函数,拿到数据
# else:
# column_data = getattr(obj, column)#反射,
# # ————————10PerfectCRM实现King_admin日期优化————————
# if type(column_data).__name__ == 'datetime':
# column_data = column_data.strftime('%Y-%m-%d %H-%M-%S')
# # ————————10PerfectCRM实现King_admin日期优化————————
#
# # ————————19PerfectCRM实现King_admin数据修改————————
#
# if index == 0: #首列
# # 生成一个链接 跳转到编辑页面 #Format参数是一个格式字符串(%s升级版)
# td_ele = '''<td><a href="/king_admin/{app_name}/{model_name}/{obj_id}/change/">{column_data}</a> </td>'''\
# .format(app_name=admin_obj.model._meta.app_label,
# model_name=admin_obj.model._meta.model_name,
# obj_id=obj.id,
# column_data=column_data)
# else:
# td_ele = '''<td>%s</td>''' % column_data
# # td_ele = '''<td>%s</td>''' % column_data #把反射来的值 拼接字符串 生成<td>
# # ————————19PerfectCRM实现King_admin数据修改————————
# row_ele += td_ele #把 <td> 拼接到上面到空字符串
# else:
# row_ele +="<td>%s</td>" %obj #把<td>拼接到上面到空字符串,crm/models.py里 def __str__(self):的返回值
# return mark_safe(row_ele) #使用mark_safe函数标记后,django将不再对该函数的内容进行转义
# # ————————09PerfectCRM实现King_admin显示注册表的内容———————— # ————————59PerfectCRM实现king_admin行内编辑————————
def render_list_editable_column(admin_obj,obj, column_obj): #处理def build_table_row(admin_obj,obj,request):的行内编辑内容
#print(table_obj,row_obj,field_obj,field_obj.name,field_obj.get_internal_type())
data_type=("PositiveSmallIntegerField","SmallIntegerField","CharField","EmailField","TextField",'ForeignKey')
# 'BooleanField',' # "IntegerField", 'BigIntegerField', "BinaryField", "FileField", "ImageField", "NullBooleanField", "URLField"
# 'DateField, "DecimalField" , "TimeField", ,"AutoField" , ,"OneToOneField" "ManyToManyField"
if column_obj.get_internal_type() in data_type : #检测数据库类型
column_data = column_obj.value_from_object(obj)
if not column_obj.choices and column_obj.get_internal_type() != "ForeignKey" : #如果不是选择框类型和外健框类型
column = '''<input data-tag='editable' type='text' name='%s' value='%s' >''' %\
(column_obj.name,
column_obj.value_from_object(obj) or '') #返回这个字段的值在给定的模型实例。
else:
# if field_obj.get_internal_type() == "ForeignKey":
# column = '''<select data-tag='editable' class='form-control' name='%s' >'''%field_obj.name
# else:
column = '''<select data-tag='editable' class='form-control' name='%s' >'''%column_obj.name #如果是选择框类型和外健框类型
for option in column_obj.get_choices(): #返回选择一个默认的空白的选择包括,使用SelectField选择这个领域。
if option[0] == column_data:
selected_attr = "selected"
else:
selected_attr = ''
column += '''<option value='%s' %s >%s</option>'''% (option[0],selected_attr,option[1])
column += "</select>"
elif column_obj.get_internal_type() == 'BooleanField': #如果是勾选类型
column_data = column_obj.value_from_object(obj)
if column_data == True: #如果前端返回的数据等于真
checked = 'checked' #勾选框显示打勾
else:
checked = '' #勾选框显示空
column = '''<input data-tag='editable' type='checkbox' name='%s' value="%s" %s> ''' %(column_obj.name,column_data,checked)
else:
column = column_obj.value_from_object(obj) ##返回这个字段的值在给定的模型实例。
return column
# ————————59PerfectCRM实现king_admin行内编辑———————— # ————————54PerfectCRM实现CRM客户报名链接————————
from django.utils.safestring import mark_safe #使用mark_safe函数标记后,django将不再对该函数的内容进行转义
from django.core.exceptions import FieldDoesNotExist
@register.simple_tag
def build_table_row(admin_obj,obj):#通过kingadmin_tags在后台处理 再传到前端
row_ele = "" #为了生成一整行返回前端
# ————————54PerfectCRM实现CRM客户报名链接————————
column_not=[]#表示不是表中字段列表
# ————————54PerfectCRM实现CRM客户报名链接———————— if admin_obj.list_display:#如果不为空,有在crm/kingadmin.py注册site.register(models.Customer,CustomerAdmin)
# ————————19PerfectCRM实现King_admin数据修改————————
#循环所有 要显示 的字符串 进行反射 展示 字段
# for column in admin_obj.list_display: #循环base_admin里class BaseAdmin下list_display = ()
for index, column in enumerate(admin_obj.list_display): # 转为列表取 下标 , 字段名
# ————————19PerfectCRM实现King_admin数据修改————————
# ————————54PerfectCRM实现CRM客户报名链接————————
try: #获取表中的字段
# ————————54PerfectCRM实现CRM客户报名链接————————
column_obj = obj._meta.get_field(column)#遍历获取 传进的参数对象
if column_obj.choices:#判断如果字段有choices属性
#获取choices的字符串(外健)
get_column_data = getattr(obj,"get_%s_display" % column) #反射,传进的参数对象,拼接字段
column_data = get_column_data()#函数,拿到数据
else:
column_data = getattr(obj, column)#反射,
# ————————10PerfectCRM实现King_admin日期优化————————
if type(column_data).__name__ == 'datetime':
column_data = column_data.strftime('%Y-%m-%d %H-%M-%S')
# ————————10PerfectCRM实现King_admin日期优化———————— # ————————19PerfectCRM实现King_admin数据修改————————
if index == 0: #首列
# 生成一个链接 跳转到编辑页面 #Format参数是一个格式字符串(%s升级版)
td_ele = '''<td><a href="/king_admin/{app_name}/{model_name}/{obj_id}/change/">{column_data}</a> </td>'''\
.format(app_name=admin_obj.model._meta.app_label,
model_name=admin_obj.model._meta.model_name,
obj_id=obj.id,
column_data=column_data)
# ————————55PerfectCRM实现CRM客户报名状态颜色变化————————
elif column in admin_obj.colored_fields: #特定字段需要显示颜色 #如果admin_obj有配置colored_fields
color_dic = admin_obj.colored_fields[column] #获取配置#字段名# 'status':{'已报名':"rgba(145, 255, 0, 0.78)",
if column_data in color_dic: #如果#已报名#有在配置里
td_ele = "<td style='background-color:%s'>%s</td>" % (color_dic[column_data],column_data) #颜色#已报名
else:
td_ele = "<td>%s</td>" % column_data
# ————————55PerfectCRM实现CRM客户报名状态颜色变化———————— # ————————59PerfectCRM实现king_admin行内编辑————————
elif column in admin_obj.list_editable: #如果获取到king_admin配置list_editable的内容
td_ele = "<td>%s</td>" % render_list_editable_column(admin_obj, obj, column_obj) #到函数处理返回
# ————————59PerfectCRM实现king_admin行内编辑———————— else:
td_ele = '''<td>%s</td>''' % column_data
# td_ele = '''<td>%s</td>''' % column_data #把反射来的值 拼接字符串 生成<td>
# ————————19PerfectCRM实现King_admin数据修改————————
# ————————54PerfectCRM实现CRM客户报名链接————————
except FieldDoesNotExist as e: # 如果没有获取到
if hasattr(admin_obj, column): # 从自定义的函数中取值
column_func = getattr(admin_obj, column)
admin_obj.instance = obj # 对象加入 column_not.append(column) # 加入非表中字段列表,
admin_obj.column_not = column_not # 对象加入
column_data = column_func()
print('column_data', column_data)
td_ele = '''<td>%s</td>''' % column_data
# ————————54PerfectCRM实现CRM客户报名链接————————
row_ele += td_ele #把 <td> 拼接到上面到空字符串
else:
row_ele +="<td>%s</td>" %obj #把<td>拼接到上面到空字符串,crm/models.py里 def __str__(self):的返回值
return mark_safe(row_ele) #使用mark_safe函数标记后,django将不再对该函数的内容进行转义
# ————————54PerfectCRM实现CRM客户报名链接————————
# ————————54PerfectCRM实现CRM客户报名链接————————
##表中自定verbose_name列名
@register.simple_tag
def verbose_name_set(admin_obj,column):
try:
verbose_name=admin_obj.model._meta.get_field(column).verbose_name.upper()#获取别名
print(verbose_name,'verbose_name_set')
print(admin_obj.model._meta,'all')
except FieldDoesNotExist as e:
verbose_name=getattr(admin_obj,column).display_name.upper()
return verbose_name
# ————————54PerfectCRM实现CRM客户报名链接———————— # ————————13PerfectCRM实现King_admin分页页数————————
#分页功能kingadmin/templates/kingadmin/table_data_list.html里 <a href="?page={{ page }}{% generate_filter_url admin_obj %}">{{ page }}
@register.simple_tag
def generate_filter_url(admin_obj): #拼接URL
url = ''
for k,v in admin_obj.filter_condtions.items():
url += "&%s=%s" %(k,v )
return url
# ————————13PerfectCRM实现King_admin分页页数———————— # ————————14PerfectCRM实现King_admin分页的省略显示————————
#分页的省略显示
@register.simple_tag
def pag_omit(request,admin_obj):#传入当前页面值
rest=''#大字符串
# ————————18PerfectCRM实现King_admin搜索关键字————————
search_key = get_search_key(request) # 搜索
# ————————18PerfectCRM实现King_admin搜索关键字————————
# ————————17PerfectCRM实现King_admin单列排序————————
order_by_url = generate_order_by_url(request) # 排序
# ————————17PerfectCRM实现King_admin单列排序————————
# ————————15PerfectCRM实现King_admin多条件过滤————————
filters = generate_filter_url(admin_obj) # 分页
# ————————15PerfectCRM实现King_admin多条件过滤————————
add_tags=False#标志位
for pages in admin_obj.querysets.paginator.page_range:
# 前两页 或 后 两页 或 当前页的前后页
if pages < 3 or pages>admin_obj.querysets.paginator.num_pages -2 or abs(admin_obj.querysets.number -pages) <=2:
#样式
add_tags=False
ele_class='' #颜色
if pages == admin_obj.querysets.number: #--如果是当前页码,颜色加深 不进链接跳转--
ele_class="active" #颜色加深
# ————————18PerfectCRM实现King_admin搜索关键字————————
# ————————17PerfectCRM实现King_admin单列排序————————
# ————————15PerfectCRM实现King_admin多条件过滤————————
# rest+='''<li class="%s"><a href="?page=%s">%s</a></li>'''%(ele_class,pages,pages) #--拼接URL--
# rest+='''<li class="%s"><a href="?page=%s%s">%s</a></li>'''%(ele_class,pages,filters,pages) #--拼接URL--
# ————————15PerfectCRM实现King_admin多条件过滤————————
# rest+='''<li class="%s"><a href="?page=%s%s%s">%s<span class="sr-only">(current)</span></a></li>'''\
# %(ele_class,pages,order_by_url,filters,pages)
# ————————17PerfectCRM实现King_admin单列排序————————
rest+='''<li class="%s"><a href="?page=%s%s%s&_q=%s">%s<span class="sr-only">(current)</span></a></li>'''\
%(ele_class,pages,order_by_url,filters,search_key,pages)
# ————————18PerfectCRM实现King_admin搜索关键字————————
else:#其他的用省略号表示
if add_tags==False:#如果不是标志位的页面
rest+='<li><a>...</a></li>'
add_tags=True#标志位为真
return mark_safe(rest) #使用mark_safe函数标记后,django将不再对该函数的内容进行转义 # ————————14PerfectCRM实现King_admin分页的省略显示———————— # # ————————15PerfectCRM实现King_admin多条件过滤————————
# #多条件过滤 table_data_list.html 传递参数
# @register.simple_tag
# def get_filter_field (filter_column,admin_obj):
# print("admin obj",admin_obj.model ,filter_column)
# field_obj = admin_obj.model._meta.get_field(filter_column)#调用内置方法
# select_ele = """<select name="%s"> """ %filter_column #拼接成下拉框返回
# for choice in field_obj.get_choices():#循环获取crm/models里class Customer(models.Model):下source_choices = ((0,'转介绍'),
# selected_condtion = admin_obj.filter_condtions.get(filter_column)
# if selected_condtion != None: #if None, 没有过滤这个条件
# print("heoe....",filter_column,selected_condtion,type(selected_condtion))#类型是 整数
# if selected_condtion == str(choice[0]): #就是选择的这个条件,整数转字符串
# selected = "selected"
# else:
# selected = ""
# else:
# selected = ""
#
# #在前端把几个条件提交到后台,后台拿着条件变成一个字典,然后进行过滤,把数据返回前端,并且把条件作为字典返回后端,因为要在前端显示已经过滤的条件。
# option_ele = """<option value="%s" %s>%s</option> """ % (choice[0],selected,choice[1])
# select_ele +=option_ele
# select_ele += "</select>"
# return mark_safe(select_ele)
# # ————————15PerfectCRM实现King_admin多条件过滤———————— # # ————————16PerfectCRM实现King_admin日期过滤————————
from django.utils.timezone import datetime,timedelta
@register.simple_tag
def get_filter_field (filter_column,admin_obj):
select_ele = """<select name='{filter_column}'><option value="">---------</option>""" #标签 字符串 #拼接成下拉框返回
field_obj = admin_obj.model._meta.get_field(filter_column)#调用内置方法
selected = ''
if field_obj.choices:
for choice_item in field_obj.choices:
if admin_obj.filter_condtions.get(filter_column) == str(choice_item[0]):
selected = "selected"
select_ele += """<option value="%s" %s>%s</option> """ % (choice_item[0], selected, choice_item[1])
selected = "" if type(field_obj).__name__ in "ForeignKey":
for choice_item in field_obj.get_choices()[1:]:
if admin_obj.filter_condtions.get(filter_column)== str(choice_item[0]): # 就是选择的这个条件,整数转字符串
selected = "selected"
select_ele += """<option value="%s" %s>%s</option> """ % (choice_item[0], selected, choice_item[1])
selected='' if type(field_obj).__name__ in ['DateTimeField', 'DateField']: # 如果是时间格式
date_els = [] # 日期条件项
today_ele = datetime.now().date() # 今天日期
date_els.append(['今天', today_ele]) # 今天
date_els.append(['昨天', today_ele - timedelta(days=1)]) # 昨天
date_els.append(['近7天', today_ele - timedelta(days=7)]) # 一周
date_els.append(['近30天', today_ele - timedelta(days=30)]) # 三十
date_els.append(['本月', today_ele.replace(day=1)]) # 本月
date_els.append(['近90天', today_ele - timedelta(days=90)]) # 90天
date_els.append(['近365天', today_ele - timedelta(days=365)]) # 365天
date_els.append(['本年', today_ele.replace(month=1, day=1)]) ##今年 for choice_item in date_els:
if admin_obj.filter_condtions.get("%s__gte" %filter_column)==str(choice_item[1]):
selected = 'selected'
select_ele += """<option value="%s" %s>%s</option> """ % (choice_item[1], selected, choice_item[0])
selected = ''
filter_column_name = "%s__gte" %filter_column
else:
filter_column_name = filter_column select_ele += "</select>"
select_ele=select_ele.format(filter_column=filter_column_name)#格式化时间的判断条件
return mark_safe(select_ele)
# ————————16PerfectCRM实现King_admin日期过滤———————— # ————————17PerfectCRM实现King_admin单列排序————————
# kingadmin排序功能
@register.simple_tag
def get_orderby_key(request,column):
current_order_by_key = request.GET.get("_o")
# ————————18PerfectCRM实现King_admin搜索关键字————————
search_key = request.GET.get("_q")
if search_key != None:
if current_order_by_key != None: #如果不为空 #肯定有某列被排序了
if current_order_by_key == column: # 判断是否相等 #当前这列正在被排序
if column.startswith("-"): #startsWith是String类中的一个方法,用来检测某字符串是否以另一个字符串开始,返回值为boolean类型
return column.strip("-") #strip去掉 文本中句子开头与结尾的符号的
else:
return "-%s&_q=%s" % (column, search_key)
return "%s&_q=%s" % (column, search_key)
else:
# ————————18PerfectCRM实现King_admin搜索关键字————————
if current_order_by_key != None: #如果不为空 #肯定有某列被排序了
if current_order_by_key == column: # 判断是否相等 #当前这列正在被排序
if column.startswith("-"): #startsWith是String类中的一个方法,用来检测某字符串是否以另一个字符串开始,返回值为boolean类型
return column.strip("-") #strip去掉 文本中句子开头与结尾的符号的
else:
return "-%s"%column
# else:
# return column
# else:
# return column
return column #同上4句
# kingadmin排序功能 # kingadmin排序功能 显示排序图标
# @register.simple_tag
# def display_order_by_icon(request, column):
# current_order_by_key = request.GET.get("_o")
# if current_order_by_key != None: #肯定有某列被排序了
# if current_order_by_key.strip("-") == column: ## 当前这列正在被排序
# if current_order_by_key.startswith("-"):
# icon = "fa-arrow-up"
# else:
# icon = "fa-arrow-down"
# ele = """<i class="fa %s" aria-hidden="true"></i>""" % icon
# return mark_safe(ele)
# return ''
# kingadmin排序功能 显示排序图标
@register.simple_tag
def display_order_by_icon(request, column):
current_order_by_key = request.GET.get("_o")
if current_order_by_key != None: #肯定有某列被排序了
if current_order_by_key.strip("-") == column: # 当前这列正在被排序 #strip去掉 文本中句子开头与结尾的符号的
if current_order_by_key.startswith("-"): #startsWith是String类中的一个方法,用来检测某字符串是否以另一个字符串开始,返回值为boolean类型
icon = "▲"
else:
icon = "▼"
ele = """<i style='color: red'>%s</i>""" % icon
return mark_safe(ele)
return '' #防止出现 None
# kingadmin排序功能 显示排序图标 # kingadmin排序功能 # 过滤后排序功能 #}
@register.simple_tag
def get_current_orderby_key(request): #注意生成的URL问题
#获取当前正在排序的字段名 #<input type="hidden" name="_o" value="{% get_current_orderby_key request %}">
current_order_by_key = request.GET.get("_o")
return current_order_by_key or ''
# kingadmin排序功能 # 过滤后排序功能 #} # kingadmin排序功能 # 过滤后排序功能 # 排序分页
@register.simple_tag
def generate_order_by_url (request):
current_order_by_key = request.GET.get("_o")
if current_order_by_key != None: # 肯定有某列被排序了
return "&_o=%s" % current_order_by_key
return ''
# kingadmin排序功能 # 过滤后排序功能 # 排序分页
# ————————17PerfectCRM实现King_admin单列排序———————— # ————————18PerfectCRM实现King_admin搜索关键字————————
@register.simple_tag
def get_search_key(request): # 搜索框里保留搜索值
search_key = request.GET.get("_q")
return search_key or ''
# ————————18PerfectCRM实现King_admin搜索关键字———————— # ————————23PerfectCRM实现King_admin数据删除————————
# <-------------------获取删除映射关系--------------------------------
@register.simple_tag
def display_all_related_obj(objs):
# 取出对象及所有相关联的数据
from django.db.models.query import QuerySet
if type(objs) != QuerySet:
objs = [objs, ]
if objs:
model_class = objs[0]._meta.model # 取表对象
model_name = objs[0]._meta.model_name # 取表名
return mark_safe(recursive_related_objs_lookup(objs))
# <-----------------递归获取映射关系--------------------------------
def recursive_related_objs_lookup(objs, name=None, conn_batch_size=0):
name = set()
print(name)
print('传递过来的objs:', objs)
# 开始标签的拼接
ul_ele = "<ul style='color: blue'>"
for obj in objs:
li_ele = '''<li>{0}:{1}</li>'''.format(obj._meta.verbose_name, obj.__str__().strip("<>"))
print('str:', obj.__str__(), '类型:', type(obj.__str__()))
print('关联的表的自定表名:', li_ele)
ul_ele += li_ele
print('拼接li_ele:', ul_ele)
# 映射关系处理
# <---------------------------特殊关联处理-----------------------------------
# 多对多关系
for m2m_field in obj._meta.local_many_to_many: # local_many_to_many返回列表,many_to_many返回元祖
print('--开始循环反射-多对多-关系处理--')
sub_ul_ele = "<ul style='color: red'>"
m2m_field_obj = getattr(obj, m2m_field.name) # 反射 如果有选项
print('反射选项:', m2m_field_obj) for m2m_data in m2m_field_obj.select_related():
print('开始循环多对多标签拼接:', m2m_data) sub_li_ele = '''<li>{0}:{1}</li>'''.format(m2m_field.verbose_name, m2m_data.__str__().strip("<>"))
sub_ul_ele += sub_li_ele
sub_ul_ele += '</ul>'
ul_ele += sub_ul_ele
print('生成完整 多对多 标签..:', ul_ele)
# <---------------------------外健关联处理------------------------------------
for related_obj in obj._meta.related_objects:
print('--开始-外健关联-处理--')
if hasattr(obj, related_obj.get_accessor_name()):
print('--判断对象中是否包含反查属性--')
accessor_obj = getattr(obj, related_obj.get_accessor_name())
print('获取反查对应的对象: ')
if hasattr(accessor_obj, 'select_related'):
print('--判断有没有获取数据的方法或属性-- ')
target_object = accessor_obj.select_related()
print('获取数据的方法或属性: ', target_object) if 'ManyToManyRel' in related_obj.__repr__():
print('--开始-外健关联-多对多-处理--.') # 生成UL
sub_ul_ele = '<ul style="color: green">'
for data in target_object:
print('开始循环-外健关联-标签拼接...', data)
sub_li_ele = '''<li>{0}:{1}</li>'''.format(data._meta.verbose_name,
data.__str__().strip("<>"))
sub_ul_ele += sub_li_ele
sub_ul_ele += '</ul>'
ul_ele += sub_ul_ele
print('-外健关联-生成完整标签:', ul_ele)
# <---------------递归处理-------------------
if len(target_object) != conn_batch_size:
print('--有下级对象存在,进行-递归-循环--')
names = target_object.__str__()
print(names, type(names))
if names == name:
print('--如果是自己关联自己,就不递归了--')
ul_ele += '</ul>'
return ul_ele
else:
print('--防止无限递归+1--')
conn_batch_size = conn_batch_size + 1
node = recursive_related_objs_lookup(target_object, name=names,
conn_batch_size=conn_batch_size)
ul_ele += node # <---------------由于使用递归,下面的标签样会发生重复,就不需要使用了--------------------
else:
print('外健关联 一对一:', accessor_obj)
target_object = accessor_obj
print("外健关联 一对一:", target_object, '属性:', type(target_object)) ul_ele += '</ul>'
return ul_ele # ————————23PerfectCRM实现King_admin数据删除———————— # ————————24PerfectCRM实现King_admin自定义操作数据————————
#自定制 actions功能 显示
@register.simple_tag
def get_admin_actions(admin_obj):
#选择功能
options = "<option class='form-control' value='-1'>-------</option>"#默认为空
actions = admin_obj.default_actions + admin_obj.actions #默认加自定制
print('默认加自定制',actions)
for action in actions:
action_func = getattr(admin_obj,action)#功能方法 #反射
if hasattr(action_func,"short_description"):#反射 如有自定义的名称执行函数方法
action_name = action_func.short_description#等于自定义的名称 #显示中文
else:
action_name = action#等于函数名称
options += """<option value="{action_func_name}">{action_name}</option> """.format(action_func_name=action, action_name=action_name)
return mark_safe(options)
# ————————24PerfectCRM实现King_admin自定义操作数据———————— # ————————27PerfectCRM实现King_admin编辑复选框————————
# 复选 框内容待选数据
@register.simple_tag
def get_m2m_available_objs(admin_obj, field_name):
'''返回m2m左侧所有待选数据'''
# c= admin_obj.model.tags.rel.model.objects.all()
# print('c',c)
# m2m_objs= admin_obj.model.tags.rel.model.objects.all()
# print('m2m_objs',m2m_objs)
m2m_model = getattr(admin_obj.model, field_name).rel # 复选框对象
m2m_objs = m2m_model.model.objects.all() # 获取到复选框所有内容
return m2m_objs # 复选 框内容已选中数据
@register.simple_tag
def get_m2m_chosen_objs(admin_obj, field_name, obj):
"""
返回已选中的列表
:param admin_obj:
:param field_name:
:param obj: 数据对象
:return:
"""
# print(["--->obj",obj])
if obj.id:
return getattr(obj, field_name).all() # 返回所有的内容
return [] # 没有数据为返回空 创建新的记录使用
# ————————27PerfectCRM实现King_admin编辑复选框————————
#kingadmin_tags.py
{#table_data_list.html#}
{## ————————08PerfectCRM实现King_admin显示注册表的字段表头————————#} {% extends 'king_master/king_index.html' %} {#继承模板#}
{% load kingadmin_tags %} {#通过自己定义标签获取中文,Django中利用filter与simple_tag为前端自定义函数的实现方法#} {% block right-container-content %} {# # ————————21PerfectCRM实现King_admin查看页面美化———————— #}
<div class="row" style="margin-bottom: 20px" >
<ol class="breadcrumb">
<li><a href="/king_admin/">主页</a></li>
<li><a href="/king_admin/{% get_app_name admin_obj.model %}/">{% get_app_name admin_obj.model %}</a></li>
<li class="active">{% get_model_verbose_name admin_obj.model%}</li>
{# # ————————22PerfectCRM实现King_admin数据添加———————— #}
{## ————————33PerfectCRM实现King_admin编辑整张表限制————————#}
{# <a href="{{ request.path }}add/" class="btn btn-sm btn-success pull-right">+添加 {% get_model_verbose_name admin_obj.model%} </a>#}
{% if not admin_obj.readonly_table %}
<a href="{{ request.path }}add/" class="btn btn-sm btn-success pull-right">+添加 {% get_model_verbose_name admin_obj.model%} </a>
{% else%}
<a href='#' class="btn btn-sm btn-success pull-right" style='color: #ff0003'>只读状态</a>
{% endif %}
{## ————————33PerfectCRM实现King_admin编辑整张表限制————————#}
{# # ————————22PerfectCRM实现King_admin数据添加———————— #} </ol> </div>
{# # ————————21PerfectCRM实现King_admin查看页面美化———————— #} {#调用kingadmin_tags里的方法 获取 base_admin的值 #}
<h4>{% get_model_verbose_name admin_obj.model %}</h4> {## ————————15PerfectCRM实现King_admin多条件过滤————————#}
{#判断 crm/kingadmin.py 里class CustomerAdmin(BaseAdmin):有没有使用list_filter = ('source',) #}
{% if admin_obj.list_filter %}
<div class="row">
<form>
{#循环 上面 list_filter = ('source',) 的字段 #}
{% for filter_column in admin_obj.list_filter %}
<div class="col-lg-1">{#最多12份 空间 #}
<div>{{ filter_column }}</div> {#到后端取值,传参数到后端, kingadmin/templatetags/kingadmin_tags.py的def get_filter_field (filter_column,admin_obj): #}
<div>{% get_filter_field filter_column admin_obj %}</div>
</div>
{% endfor %}
<div>
<input type="submit" class="btn btn-success" value="过滤">
</div> {## ————————17PerfectCRM实现King_admin单列排序————————#}
<div>
{# 隐藏 #} {# 过滤后排序功能 #}
<input type="hidden" name="_o" value="{% get_current_orderby_key request %}">
</div>
{## ————————17PerfectCRM实现King_admin单列排序————————#} {## ————————18PerfectCRM实现King_admin搜索关键字————————#}
<hr> {#过滤后搜索功能1#} {## 搜索框里保留搜索值 #}
{# <input type="text" name="_q" value="{% get_search_key request %}">#} <div class="row">
<div class="col-lg-2">
<input type="text" name="_q" value="{% get_search_key request %}">
</div>
<div class="col-lg-2">
<input type="submit" class="btn btn-success" value="搜索">
</div> <div style='color: red'> 搜索条件包含:
{% for search_field in admin_obj.search_fields %}
{{ search_field }}
+
{% endfor %}
</div>
</div>
{## ————————18PerfectCRM实现King_admin搜索关键字————————#} </form>
</div>
{% endif %}
{## ————————15PerfectCRM实现King_admin多条件过滤————————#} {## ————————24PerfectCRM实现King_admin自定义操作数据————————#}
<hr>
<div class="row">
<form method="post" onsubmit="return ActionValidation(this)">{% csrf_token %}
<div class="col-lg-2">
<select name="action_select">
{% get_admin_actions admin_obj %}
</select>
</div> <div class="col-lg-2">
<input type="submit" class="btn btn-success" value="执行">
</div>
</form>
</div>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#} <table class="table table-hover">
<thead> <tr>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#}
<th><input type="checkbox" onclick="SelectAll(this);"></th>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#} {## ————————17PerfectCRM实现King_admin单列排序————————#}
{#循环调用kingadmin/base_admin里的class BaseAdmin下的list_display = () 方法#}
{# {% for column in admin_obj.list_display %}#}
{# <th>{{ column }}</th>#}
{# {% endfor %}#}
{# #}
{% for column in admin_obj.list_display %}
{# <th>{{ column }}</th>#} {#过滤功能1#}
{#排序功能1#}
<th>
{# <a href="?_o={{ column }}">{{ column }}</a>#} {#http://127.0.0.1:8000/kingadmin/crm/customer/?_o=qq#}
{## kingadmin排序功能#}
{# <a href="?_o={% get_orderby_key request column %}">{{ column }}</a>#} {## ————————54PerfectCRM实现CRM客户报名链接————————#}
{## kingadmin排序功能#} {# 过滤后排序功能 #}
{# <a href="?_o={% get_orderby_key request column %}{% generate_filter_url admin_obj %}">{{ column }}</a>#}
{##}
{#显示排序图标#}
{# {% display_order_by_icon request column %}#}
{## ————————54PerfectCRM实现CRM客户报名链接————————#}
{## ————————54PerfectCRM实现CRM客户报名链接————————#}
<!-- 非表中的字段-->
{% if column in admin_obj.column_not %}
<a>{% verbose_name_set admin_obj column %}</a>
{% else %}
<a href="?_o={% get_orderby_key request column %}{% generate_filter_url admin_obj %}">{% verbose_name_set admin_obj column %}</a>
{% display_order_by_icon request column %}
{% endif %}
{## ————————54PerfectCRM实现CRM客户报名链接————————#}
</th>
{#排序功能1#}
{% endfor %}
{## ————————17PerfectCRM实现King_admin单列排序————————#}
</tr>
</thead> {## ————————09PerfectCRM实现King_admin显示注册表的内容————————#} {## ————————59PerfectCRM实现king_admin行内编辑————————#}
{# <tbody>#}
<tbody id="model_table_data">
{## ————————59PerfectCRM实现king_admin行内编辑————————#} {#循环调用kingadmin/views 里的def table_data_list下的admin_obj.querysets #}
{% for obj in admin_obj.querysets %}
<tr>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#}
<td><input tag="obj_checkbox" type="checkbox" value="{{ obj.id }}"> </td>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#} {#通过kingadmin_tags在后台处理 再传到前端 #}
{#调用kingadmin/templateags/kingadmin_tags 里的def build_table_row(admin_obj,obj):#}
{## ————————19PerfectCRM实现King_admin数据修改————————#}
{% build_table_row admin_obj obj %}{# kingadmin动态生成model编辑 #}
{## ————————19PerfectCRM实现King_admin数据修改————————#} </tr>
{% endfor %}
</tbody>
{## ————————09PerfectCRM实现King_admin显示注册表的内容————————#}
</table> {## ————————24PerfectCRM实现King_admin自定义操作数据————————#}
<div class="radio">
数据总量: {{ admin_obj.querysets.paginator.count }} 条
</div>
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#} {## ————————12PerfectCRM实现King_admin分页上下页————————#}
{# <div class="row">#}
{# <div class="pagination">#}
{# <span class="step-links">#}
{# {% if admin_obj.querysets.has_previous %}#}
{##}
{## ————————15PerfectCRM实现King_admin多条件过滤————————#}
{# <a href="?page={{ admin_obj.querysets.previous_page_number }}#}
{# <a href="?page={{ admin_obj.querysets.previous_page_number }}{% generate_filter_url admin_obj %}">上一页 </a>#}
{## ————————15PerfectCRM实现King_admin多条件过滤————————#}
{##}
{# {% endif %}#}
{##}
{# <span class="current">#}
{# 第{{ admin_obj.querysets.number }}页,共{{ admin_obj.querysets.paginator.num_pages }}页#}
{# </span>#}
{##}
{# {% if admin_obj.querysets.has_next %}#}
{##}
{## ————————15PerfectCRM实现King_admin多条件过滤————————#}
{# <a href="?page={{ admin_obj.querysets.next_page_number }}#}
{# <a href="?page={{ admin_obj.querysets.next_page_number }}{% generate_filter_url admin_obj %}">下一页</a>#}
{## ————————15PerfectCRM实现King_admin多条件过滤————————#}
{##}
{# {% endif %}#}
{# </span>#}
{# </div>#}
{# </div>#}
{## ————————12PerfectCRM实现King_admin分页上下页————————#} {## ————————13PerfectCRM实现King_admin分页页数————————#}
{# <nav aria-label="...">#}
{# <ul class="pagination">#}
{# <li class="disabled"></li>#}
{# {% for page in admin_obj.querysets.paginator.page_range %} {#循环 分页 范围#}
{##}
{# {% if page == admin_obj.querysets.number %} {#当前页高亮,否则不加高亮#}
{# <li class="active">#}
{# {% else %}#}
{# <li >#}
{# {% endif %}#}
{##}
{#后台拼接返回,kingadmin/templatetags/kingadmin_tags.py 里def generate_filter_url(admin_obj):#}
{# <a href="?page={{ page }}{% generate_filter_url admin_obj %}">{{ page }}</a>#}
{# </li>#}
{# {% endfor %}#}
{# </ul>#}
{# </nav>#}
{## ————————13PerfectCRM实现King_admin分页页数————————#} {## ————————14PerfectCRM实现King_admin分页的省略显示————————#} <div class="row panel-body">
<nav aria-label="...">
<ul class="pagination">
<!--如果有上一页-->
{% if admin_obj.querysets.has_previous %}
{## ————————18PerfectCRM实现King_admin搜索关键字————————#}
{## ————————17PerfectCRM实现King_admin单列排序————————#}
{# <li><a href="?page={{ admin_obj.querysets.previous_page_number }}{% generate_filter_url admin_obj %}"#}
{# aria-label="Previous"><span aria-hidden="true">«</span></a></li>#} {#获取上一个数字#} {# kingadmin排序功能 # 过滤后排序功能#排序#} {#分页#}
{#<li><a href="?page={{ admin_obj.querysets.previous_page_number }}{% generate_order_by_url request %}{% generate_filter_url admin_obj %}"#}
{# aria-label="Previous"><span aria-hidden="true">上页</span></a></li>#}
{## ————————17PerfectCRM实现King_admin单列排序————————#}
<li><a href="?page={{ admin_obj.querysets.previous_page_number }}
{% generate_order_by_url request %}{% generate_filter_url admin_obj %}&_q={% get_search_key request %}"
aria-label="Previous"><span aria-hidden="true">上页</span></a></li>
{## ————————18PerfectCRM实现King_admin搜索关键字————————#}
{% else %}
<li class="disabled">
<a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li>
{% endif %}
<!--#分页的省略显示 kingadmin/templatetags/kingadmin_tags.py里def pag_omit(request,admin_obj):-->
{% pag_omit request admin_obj %}
<!--如果有下一页-->
{% if admin_obj.querysets.has_next %}
{## ————————18PerfectCRM实现King_admin搜索关键字————————#}
{## ————————17PerfectCRM实现King_admin单列排序————————#}
{# <li><a href="?page={{ admin_obj.querysets.next_page_number }}{% generate_filter_url admin_obj %}"#}
{# aria-label="Previous"><span aria-hidden="true">»</span></a></li>#} {#<li><a href="?page={{ admin_obj.querysets.next_page_number }}{% generate_order_by_url request %}{% generate_filter_url admin_obj %}"#}
{# aria-label="Previous"><span aria-hidden="true">下页</span></a></li>#}
{## ————————17PerfectCRM实现King_admin单列排序————————#}
<li><a href="?page={{ admin_obj.querysets.next_page_number }}
{% generate_order_by_url request %}{% generate_filter_url admin_obj %}&_q={% get_search_key request %}"
aria-label="Previous"><span aria-hidden="true">下页</span></a></li>
{## ————————18PerfectCRM实现King_admin搜索关键字————————#} {% else %}
<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">»</span></a>
</li>
{% endif %}
</ul>
</nav>
</div>
{## ————————14PerfectCRM实现King_admin分页的省略显示————————#} {## ————————59PerfectCRM实现king_admin行内编辑————————#}
{% if admin_obj.list_editable %}
<div>
<form method="post" onsubmit="return PrepareFormData(this)">{% csrf_token %}
<button class="btn btn-info pull-right">保存</button>
</form>
</div>
{% endif %}
{## ————————59PerfectCRM实现king_admin行内编辑————————#} {% endblock %}
{## ————————08PerfectCRM实现King_admin显示注册表的字段表头————————#} {## ————————59PerfectCRM实现king_admin行内编辑————————#}
{% block js %}
<script>
$(document).ready(function () {
$('input[type="checkbox"][data-tag="editable"]').change(function() {
if(this.checked) {
// do something when checked
console.log("checked...")
$(this).val("True") }else {
console.log("unchekc")
$(this).val("False")
}
});
});//end doc ready
function PrepareFormData(form_ele) {
var form_data = [];
$("#model_table_data tr").each(function () {
var obj_id = $(this).children().first().find("input").val(); console.log(obj_id);
if (obj_id){ //table obj row
var row_data = {};//all columns need to be updated
$(this).find("[data-tag='editable']").each(function () {
//console.log($(this).attr("name") + "----" +$(this).val())
row_data[$(this).attr("name")] = $(this).val();
});//end find each
row_data['id'] = obj_id; form_data.push(row_data);
} });//end each
console.log(form_data)
var ele = '<input type="hidden" name="editable_data" value=' + JSON.stringify(form_data) + ' >';
$(form_ele).append(ele); return true;
}
</script>
{% endblock %}
{## ————————59PerfectCRM实现king_admin行内编辑————————#}
{#table_data_list.html#}
{#king_base.html#}
{## ————————02PerfectCRM创建ADMIN页面————————#}
{#模板文件 king_base.html#}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
{# <meta> 元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。#}
{# <meta> 标签位于文档的头部,不包含任何内容。<meta> 标签的属性定义了与文档相关联的名称/值对。#}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content=""> <link rel="icon" href="/static/king_img/king_logo.jpg">{# icon,指的是图标 #}
<title>KingAdmin</title> {# 页面头部显示#} {# 使用link来调用外部的css文件#}
<link rel="stylesheet" href="/static/king_css/bootstrap.css" /> {#导航栏样式#}
<link rel="stylesheet" href="/static/king_css/dashboard.css" /> {#指示板样式#} {## ————————27PerfectCRM实现King_admin编辑复选框————————#}
<link rel="stylesheet" href="/static/king_css/king_admin_change.css" /> {#编辑复选框样式#}
{## ————————27PerfectCRM实现King_admin编辑复选框————————#} </head> <body> {% block body %}{#自定义内容 body#}{% endblock %} {# 将纯JavaScript的语句另外保存在一个"*.js"的文件中,需要时再调用。#}
<script src="/static/king_js/jquery.js"></script> {# jQuery 是一个 JavaScript库,极大地简化了 JavaScript 编程。#}
<script src="/static/king_js/bootstrap.js"></script> {#指示板JS事件#} {## ————————24PerfectCRM实现King_admin自定义操作数据————————#}
<script src="/static/king_js/king_admin_js.js"></script> {#自定义JS事件#}
{## ————————24PerfectCRM实现King_admin自定义操作数据————————#} {## ————————27PerfectCRM实现King_admin编辑复选框————————#}
<script src="/static/king_js/king_admin_change.js"></script> {#编辑复选框JS事件#}
{## ————————27PerfectCRM实现King_admin编辑复选框————————#} {## ————————59PerfectCRM实现king_admin行内编辑————————#}
{% block js %}{# 独立的JS#}{% endblock %}
{## ————————59PerfectCRM实现king_admin行内编辑————————#} </body>
</html> {## ————————02PerfectCRM创建ADMIN页面————————#}
{#king_base.html#}
如果感觉本章博客对您有帮助,请尽情打赏吧!
Django项目:CRM(客户关系管理系统)--69--59PerfectCRM实现king_admin行内编辑的更多相关文章
- Django项目:CRM(客户关系管理系统)--84--74PerfectCRM实现CRM权限和权限组限制访问URL
#models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...
- Django CRM客户关系管理系统
CRM需求分析 随着信息化时代带来的科技创新,CRM客户关系管理系统带来的效益在已经成为很多企业提高竞争优势的一分部,CRM客户关系管理系统将企业管理和客户关系管理集成到统一的平台,其系统功能主要体现 ...
- Django项目:CRM(客户关系管理系统)--85--75PerfectCRM实现CRM扩展权限
# sales_urls.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.conf.urls import url from bpm. ...
- Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色
#models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...
- Django项目:CRM(客户关系管理系统)--72--62PerfectCRM实现CRM讲师讲课记录
#urls.py """PerfectCRM URL Configuration The `urlpatterns` list routes URLs to views. ...
- Django项目:CRM(客户关系管理系统)--68--58PerfectCRM实现king_admin批量生成上课记录
# kingadmin.py # ————————04PerfectCRM实现King_admin注册功能———————— from crm import models #print("ki ...
- CRM 客户关系管理系统
CRM(Customer Relationship Manager)客户关系管理系统 企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的交互,从而提升其管理方 ...
- CRM客户关系管理系统-需求概设和详设
大概设计 大概设计就是对需求进行一个整体性分析,把需要实现的功能都列出来,对于客户关系管理系统,我们需要从角色出发,从而确定有哪些需求,最好是画个思维导图 首先我们是为培训学校这么一个场景来开发的,所 ...
- CRM客户关系管理系统 北京易信软科信息技术有限公司
北京易信软科信息技术有限公司 推出大型erp系统,库存管理系统,客户关系管理系统,车辆登记管理系统,员工管理系统,采购管理系统,销售管理系统,为您的企业提供最优质的产品服务 北京易信软科您可信赖的北京 ...
随机推荐
- H5 回到顶部按钮
//这里我用的是svg,所以代码老长了,可以把svg部分换成自己的图片什么的$(function(){ var obj = $('<div style="width:1.3rem;po ...
- JavaScript的函数进阶
函数进阶 1立即执行函数表达式 立即执行的函数表达式的英文全称为Immediately Invoked Function Expression,简称就为IIFE.这是一个如它名字所示的那样,在定义后就 ...
- arcmap分类标注问题
在给图层标注的时候,经常出现冲突后有些标注出不来,需要将某些个别的点要素进行标注位置调整,如下图: 处理步骤如下, (1)打开Maplex标注引擎.从ToolBars中打开Labeling工具,勾选U ...
- QtCreator 生成动态库
在Windows平台上,QtCreator( MinGW4.9.2 )创建动态库,最终生成的文件是libHello.a.Hello.dll和hello.o这3个文件(假设在D:/Lib文件夹下面) 在 ...
- day19_生成器
20180730 初次上传 20180731 更新,4.列表生成式,以及部分注释 #!/usr/bin/env python # -*- coding:utf-8 -*- # ************ ...
- C语言进阶学习第一章
1.在C语言里面使用scanf给某个变量赋值时候,如果成功返回1,失败返回0:测试代码如下: /***假如在键盘输入的不是整形数据,则输出0,否则输出1***/ void main() { int a ...
- Tomcat的8080、8005、8009端口
8080是http 1.1 connector,也就是接收处理http请求的端口,如果你只用一个tomcat处理所有请求,可以只使用这个connector. 8005是 tomcat接受关闭指令的端口 ...
- vue引入外部css和js
<template> <div id="app" > </div> </template> <script src=" ...
- layui之input里格式验证
form.verify({ title: function(value){ if(value.length < 5){ retu ...
- <每日一题>题目11:以文件夹名称作为参数,返回该文件夹下所有文件的路径
''' 分析: 1.知道文件夹名称(假设是形如:E:\\software\\Notepad++),很显然可以通过OS模块去求 2.OS.listdir(sPath),列出文件夹内所有的文件和文件夹,以 ...