###############  admin基本认识和常用的定制功能    ###############

stark组件

对admin的基本认识
1,就是一个app,嵌入到了django里面,你可以在settings中看到
2,就是一个web后台管理工具,使用它可以更加的方便
3,通常我们在生成项目时会在 urls.py 中自动设置好url访问路径
urlpatterns = [
url(r'^admin/', admin.site.urls)
]
4,启动开发服务器,然后在浏览器中访问 http://127.0.0.1:8000/admin/
5,你通过命令 python manage.py createsuperuser 来创建超级用户
6,使用的时候先注册数据模型:admin.site.register(models.UserInfo)
7,点击进入会展示数据,默认就是把这个对象打印出来,复杂的,需要定制的,需要利用ModelAdmin进行操作
class CourseConfig(admin.ModelAdmin):
pass
admin.site.register(Course,CourseConfig) ####################### class UserInfoConfig(admin.ModelAdmin):
list_display=["id","name","username","password","email","depart"] # 定制显示的列。不能放多对多的字段
list_display_links=["username"] # 定制列可以点击跳转到详情页面,
list_filter=["depart"] # 定制右侧快速筛选。
list_editable=["email"] # 可以编辑的列,可以编辑就不能是list_display_links字段了,
search_fields=["username"] # 模糊搜索的功能 # 定义action的函数
def func(self,request,queryset):
print(request,queryset)
queryset.update(email="1212@qq.com")
func.short_description = "批量初始化操作" actions=[func,] # 定制action中的操作
fields=["username"] # 查看详情和新增页面,可以控制显示的字段
ordering=["-id"] # 数据排序规则,倒序在字段前面加符号, admin.site.register(UserInfo,UserInfoConfig)

###############  admin的url设计的基础知识点   ###############

admin的url是怎么设计的,这是核心,
urlpatterns = [
url(r'^admin/', admin.site.urls), # 为什么这一句能能够生成多条url,
]

第一个知识点,url的嵌套使用

def yuan(request):
return HttpResponse("Yuan") def test01(request):
return HttpResponse("test01") def test02(request):
return HttpResponse("test02") def test03(request):
return HttpResponse("test03") def test04(request):
return HttpResponse("test04") def test05(request):
return HttpResponse("test05") urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^yuan/', ([
url(r'^test01/', ([
url(r'^test04/', test04), # http://127.0.0.1:8000/yuan/test01/test04/
url(r'^test05/', test05),
], None, None)),
url(r'^test02/', test02),
url(r'^test03/', test03),
], None, None))
]

第二个知识点:单例模式,

# 单例模式

# 一个类只允许实例一个对象

# class Singleton(object):
# _instance = None
# def __new__(cls, *args, **kw):
# if not cls._instance:
# cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
# return cls._instance
#
# class MyClass(Singleton):
# a = 1
#
#
# one = MyClass()
# one.a=3
#
# two = MyClass()
# print(two.a) # 这个地方就是3,因为one和two指向的同一个内存空间,one改掉了a=3,所以two取值的时候就是3
#
# # print(one==two)
# # print(id(one),id(two)) # 第二种方法
###########################
# 第一个文件
class My_Singleton(object):
x =12
def foo(self):
print(self.x)
my_singleton = My_Singleton() # 这是一个关键的一步 print("OK") ###################
# 第二个文件
from mysingleton import my_singleton
def foo():
print(id(my_singleton))
############
# 第三个文件
from mysingleton import my_singleton,My_Singleton # a=My_Singleton()
# b=My_Singleton()
#
# print(id(a))
# print(id(b)) # 这是拿的类对象,而不是实例对象,所以,这两个不一样, print(id(my_singleton))
from mysingleton import my_singleton
print(id(my_singleton))
from func import *
foo() # 这三次都是拿的实例对象,所以id的结果都是一样的,

############### admin的url设计    ###############

第一个注册:

# 注册

self._registry = {}
self._registry[model] = admin_class(model, self)
# 注册的时候,是定义了一个字典,然后以model表为键,以对应的自定义类为值,生成对应的字典,

第二个url设置

def add(request):
return HttpResponse("add")
def delete(request,id):
return HttpResponse("delete")
def change(request,id):
return HttpResponse("change")
def list_view(request):
return HttpResponse("list_view") def get_urls2(): temp=[]
temp.append(url(r"^add/",add))
temp.append(url(r"^(\d+)/delete/",delete))
temp.append(url(r"^(\d+)/change/",change))
temp.append(url(r"^$",list_view))
print("temp2",temp)
# [
# <RegexURLPattern None ^add/>,
# <RegexURLPattern None ^(\d+)/delete/>,
# <RegexURLPattern None ^(\d+)/change/>,
# <RegexURLPattern None ^$>
# ]
return temp def get_urls(): temp=[]
print("_registry",admin.site._registry) for model,admin_class_obj in admin.site._registry.items():
print("model",model) # 所有的注册模型表 # < class 'app01.models.Book'>-----> "book" "app01"
# < class 'app01.models.Room'>-----> "room" "app01"
print("===>",model._meta.model_name)
print("===>",model._meta.app_label) model_name=model._meta.model_name # 对应的model表的名字
app_label=model._meta.app_label # 对应的app名字
temp.append(url(r"%s/%s/"%(app_label,model_name),(get_urls2(),None,None)))
print("temp",temp)
"""
[
<RegexURLResolver <RegexURLPattern list> (None:None) auth/group/>,
<RegexURLResolver <RegexURLPattern list> (None:None) auth/user/>,
<RegexURLResolver <RegexURLPattern list> (None:None) crm/userinfo/>
]
""" return temp urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^yuan/', (get_urls(), None, None))
]

###############  模仿admin-stark组件的url设计    ###############

class ModelStark(object):

    def __init__(self,model,site):
self.model=model # 谁调用的就是那个表
self.site=site def add_view(self, request):
return HttpResponse("add_view") def change_view(self, request, id):
return HttpResponse("change_view") def delete_view(self, request, id):
return HttpResponse("delete_view") def list_view(self, request):
return HttpResponse("list_view") def get_urls_2(self): temp = [] model_name=self.model._meta.model_name
app_label=self.model._meta.app_label temp.append(url(r"^add/", self.add_view))
temp.append(url(r"^(\d+)/delete/", self.delete_view))
temp.append(url(r"^(\d+)/change/", self.change_view))
temp.append(url(r"^$", self.list_view)) return temp @property
def urls_2(self):
print(self.model)
return self.get_urls_2(), None, None class StarkSite(object):
def __init__(self):
self._registry={} def register(self,model,stark_class=None):
if not stark_class:
stark_class=ModelStark self._registry[model] = stark_class(model, self) # 括号内的两个参数,就是ModelStark默认的两个参数,self就是site def get_urls(self):
temp=[]
for model,stark_class_obj in self._registry.items():
model_name=model._meta.model_name
app_label=model._meta.app_label
# 分发增删改查
temp.append(url(r"^%s/%s/"%(app_label,model_name),stark_class_obj.urls_2)) '''
url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
url(r"^app01/book/",ModelStark(Book).urls_2), '''
return temp @property
def urls(self):
return self.get_urls(),None,None site=StarkSite() # 单例模式

##############  stark组件需要实现的功能    ###############

在完成了注册和url设计之后,stark组件需要完成什么功能

1,查询页面
1.1 表头展示,可以定制展示的列,
1.2 表内容展示,删除 编辑,复选框的功能
1.3 查询功能,可以定义查询的字段,
1.4 action功能,可以定制批量操作
1.5 筛选功能,可以定制筛选的字段,
1.6 分页功能
这是最为复杂的部分, 2,新增页面
2.1 一个重要的pop功能, 3,删除页面
这个简单 4,编辑页面,
这个简单,和新增页面很相似,只需要把要编辑的数据带到页面展示, 整个重写,使用到了
1,django
2,admin
3,前端,js,html,bootstrap,jQuery,

##############  stark-service    ###############

# by luffycity.com
from django.conf.urls import url from django.shortcuts import HttpResponse,render,redirect
from django.urls import reverse
from django.db.models import Q
from django.utils.safestring import mark_safe from stark.utils.page import Pagination
from django.db.models.fields.related import ManyToManyField,ForeignKey
class ShowList(object):
def __init__(self,config,data_list,request):
self.config=config # 这里的config就是用来接收传递的modelstark类的,下面就可以使用config调用modelstark里面的方法了,
self.data_list=data_list # 这个datalist是需要展示的数据
self.request=request # 为什么需要传递request?因为需要在这个里面获取page参数,是第几页
#分页
data_count=self.data_list.count()
current_page=int(self.request.GET.get("page",1))
base_path=self.request.path self.pagination=Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=10, pager_count=11, )
self.page_data=self.data_list[self.pagination.start:self.pagination.end] # actions
self.actions=self.config.new_actions() # [patch_init,] # 获取modelstark中配置的action列表, def get_filter_linktags(self):
print("list_filter:",self.config.list_filter)
link_dic={} # 格式是{筛选字段1:筛选值1,筛选字段2:筛选值2}
import copy for filter_field in self.config.list_filter: # ["title","publish","authors",]
params = copy.deepcopy(self.request.GET) # 复制一份方便操作 cid=self.request.GET.get(filter_field,0) # 这是获取到前端拼接的id, print("filter_field",filter_field) # "publish"
filter_field_obj=self.config.model._meta.get_field(filter_field) # 这是拿到的字段对象
print("filter_field_obj",filter_field_obj)
print(type(filter_field_obj))
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.related import ManyToManyField
# 举例说明:拿到出版社关联的书籍,筛选是所有关联的出版社,拿到作者关联的书籍,筛选是所有关联的作者,怎么获取?
print("rel======...",filter_field_obj.rel) if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
data_list=filter_field_obj.rel.to.objects.all()# 【publish1,publish2...】
# filter_field_obj.rel.to,这种特殊写法,只有字段有关联表的时候才有意义,一对多,和多对多的,
else:
data_list=self.config.model.objects.all().values("pk",filter_field)
print("data_list",data_list) temp=[]
# 处理全部标签
if params.get(filter_field): # filter_field 这是筛选的字段,如果有筛选值,就删掉,
del params[filter_field]
temp.append("<a href='?%s'>全部</a>"%params.urlencode())
else:
temp.append("<a class='active' href='#'>全部</a>") # 处理数据标签
for obj in data_list:
if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
pk=obj.pk
text=str(obj)
params[filter_field] = pk
else: # data_list= [{"pk":1,"title":"go"},....]
print("========")
pk=obj.get("pk")
text=obj.get(filter_field)
params[filter_field] =text # 处理单表查询 _url=params.urlencode()
if cid==str(pk) or cid==text: # 这是为了实现点击选中的标签,展示深蓝色,active
link_tag="<a class='active' href='?%s'>%s</a>"%(_url,text)
else:
link_tag = "<a href='?%s'>%s</a>" % (_url, text)
temp.append(link_tag) link_dic[filter_field]=temp return link_dic def get_action_list(self): # 拿到action操作,放到页面去渲染
temp=[]
for action in self.actions: # 这是配置的action列表,循环这个列表,每一个action就是每一个函数,
temp.append({
"name":action.__name__, # 获取函数的名字,作为值
"desc":action.short_description # 获取函数的描述,作为展示short_description,这是函数的一个动态属性
}) # [{"name":""patch_init,"desc":"批量初始化"}] print("temp",temp)
return temp def get_header(self):
# 构建表头
header_list = []
print("header",
self.config.new_list_play()) # [checkbox,"pk","name","age",edit ,deletes] 【checkbox ,"__str__", edit ,deletes】 for field in self.config.new_list_play(): if callable(field):
# header_list.append(field.__name__) # field.__name__函数的名字
val = field(self.config, header=True) # header=True,header默认是false,这个再去拿值的之后就会拿到汉字了
header_list.append(val) else:
if field == "__str__": # 这是没有自定义的情况
header_list.append(self.config.model._meta.model_name.upper()) # 这是展示表名的大写作为表头
else: # 这是自定义的情况
# header_list.append(field)
val = self.config.model._meta.get_field(field).verbose_name # 这是获取到了表里面的字段,verbose_name这是字段的中文
header_list.append(val)
return header_list def get_body(self):
# 构建表单数据
new_data_list = []
for obj in self.page_data:
temp = [] for filed in self.config.new_list_play(): # ["__str__",] ["pk","name","age",edit] 这一步应该把编辑,删除,复选框都加进来了 if callable(filed): # callable判断是否是一个可调用的,如果是一个字符串就是False,如果是一个方法就是true
print("obj-----:",obj)
val = filed(self.config, obj)
else:
try:
field_obj=self.config.model._meta.get_field(filed)
if isinstance(field_obj,ManyToManyField): # 多对多的时候如何展示数据
ret = getattr(obj,filed).all() # 这是获取到多对多的情况,可能会有多个值,
t=[]
for mobj in ret:
t.append(str(mobj))
val=",".join(t) # 拼成逗号隔开的样子,展示出来,
else:
print("====>",field_obj.choices)
if field_obj.choices:
val = getattr(obj, "get_"+filed+"_display") # 这个obj是每一条数据,filed是每一条数据应该显示的字段,
else:
val = getattr(obj, filed)
if filed in self.config.list_display_links: # 如果是一个可以点击的字段,要特殊处理成为超链接
# "app01/userinfo/(\d+)/change"
_url = self.config.get_change_url(obj)
val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) except Exception as e:
val = getattr(obj, filed) temp.append(val) new_data_list.append(temp)
return new_data_list '''
[
[1,"alex",12],
[1,"alex",12],
[1,"alex",12],
[1,"alex",12], ] ''' class ModelStark(object): list_display=["__str__",]
list_display_links=[]
modelform_class=None
search_fields=[]
actions = []
list_filter=[] def patch_delete(self, request, queryset):
"""批量删除"""
queryset.delete() patch_delete.short_description = "批量删除" def __init__(self,model,site):
self.model=model
self.site=site # 删除 编辑,复选框
def edit(self,obj=None,header=False):
if header:
return "操作"
#return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
_url=self.get_change_url(obj) return mark_safe("<a href='%s'>编辑</a>"%_url) def deletes(self,obj=None,header=False):
if header:
return "操作"
# return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk) _url=self.get_delete_url(obj) return mark_safe("<a href='%s'>删除</a>" % _url) def checkbox(self,obj=None,header=False):
if header:
return mark_safe('<input id="choice" type="checkbox">') return mark_safe('<input class="choice_item" type="checkbox" name="selected_pk" value="%s">'%obj.pk)
# 这一步非常的重要,因为在配合action去取到选中的数据, def get_modelform_class(self):
"""如果客户定制了用客户定制的,如果没有没有定制使用默认的,"""
if not self.modelform_class:
from django.forms import ModelForm # 这个涉及到了form表单的内容,
from django.forms import widgets as wid
class ModelFormDemo(ModelForm): # 可以在每一个app中的stark里面,对每一个model进行重写这个类,就可以定制了
class Meta:
model = self.model
fields = "__all__"
labels={
""
} # 可以在每一个app中的stark里面,labels可以对字段进行设置汉字,格式是键:值的方式,
return ModelFormDemo
else:
return self.modelform_class def get_new_form(self,form):
"""这是pop弹出的窗口对象的方法,"""
for bfield in form:
from django.forms.boundfield import BoundField
print(bfield.field) # 字段对象
print("name",bfield.name) # 字段名(字符串)
print(type(bfield.field)) # 字段类型
from django.forms.models import ModelChoiceField
if isinstance(bfield.field,ModelChoiceField):
bfield.is_pop=True # 这是动态给多对多的字段加属性
# 怎么拿到关联表的名字,和它所属的APP呢,
print("=======>",bfield.field.queryset.model) # 一对多或者多对多字段的关联模型表
related_model_name=bfield.field.queryset.model._meta.model_name
related_app_label=bfield.field.queryset.model._meta.app_label _url=reverse("%s_%s_add"%(related_app_label,related_model_name)) # 反向解析进入对应的添加页面,
bfield.url=_url+"?pop_res_id=id_%s"%bfield.name # 动态加字段,字段名(字符串) return form def add_view(self, request):
ModelFormDemo = self.get_modelform_class() # 这是返回一个类
form = ModelFormDemo() # 使用这个类实例化一个对象出来, form=self.get_new_form(form) if request.method=="POST": # 点击提交按钮要做的事情
form = ModelFormDemo(request.POST)
if form.is_valid():
obj=form.save() # 这都是form表单的功能,校验通过就保存到数据库, pop_res_id=request.GET.get("pop_res_id") if pop_res_id:
res ={"pk":obj.pk,"text":str(obj),"pop_res_id":pop_res_id}
import json
return render(request, "pop.html", {"res":res})
else:
return redirect(self.get_list_url())
print("locals()",locals())
"""
{
'form': <ModelFormDemo bound=False, valid=Unknown, fields=(qq;name;gender;education;graduation_school;major;experience;work_status;company;salary;source;referral_from;course;status;consultant;recv_date;last_consult_date)>,
'ModelFormDemo': <class 'stark.service.stark.ModelStark.get_modelform_class.<locals>.ModelFormDemo'>,
'request': <WSGIRequest: GET '/stark/crm/customer/add/'>,
'self': <crm.stark.CusotmerConfig object at 0x000000000D1FBC18>
}
"""
return render(request, "add_view.html", locals()) # Python 的内建函数 locals() 。它返回的字典对所有局部变量的名称与值进行映射。 def delete_view(self, request, id):
url = self.get_list_url()
if request.method=="POST":
self.model.objects.filter(pk=id).delete()
return redirect(url) return render(request, "delete_view.html", locals()) def change_view(self, request, id):
ModelFormDemo = self.get_modelform_class() # 获取这个类,可以控制展示的字段等信息
print("=====id",id)
edit_obj = self.model.objects.filter(pk=id).first() if request.method=="POST":
form = ModelFormDemo(request.POST,instance=edit_obj) # 这个instance也是djangoform表单的功能,
if form.is_valid():
form.save()
return redirect(self.get_list_url()) # 提交之后返回到列表页 print("locals()",locals())
return render(request, "change_view.html", locals()) print("***********",edit_obj)
form = ModelFormDemo(instance=edit_obj) # 和新增页面一样,只需要加一个instance
form = self.get_new_form(form) return render(request, "change_view.html", locals()) def new_list_play(self):
"""这个方法不只是把每一条数据的字段放进来了,还把编辑,删除,复选框也放进来了,"""
temp=[]
temp.append(ModelStark.checkbox) # 复选框加入
temp.extend(self.list_display) # 自定义字段加入,这个地方还可以自己自定义函数,传进来,
if not self.list_display_links: # 如果已经有点击链接可以编辑的入口了,就不需要编辑这一栏了,
temp.append(ModelStark.edit) # 编辑加入
temp.append(ModelStark.deletes) # 删除加入
return temp def new_actions(self):
temp=[]
temp.append(ModelStark.patch_delete)
temp.extend(self.actions) # 这个里面就可能会有自定义的action,这样组成一个新的action, return temp def get_change_url(self,obj): # 这一个功能多个地方使用,所以封装到一个方法里面,
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
print("obj===========",obj)
# from django.urls import reverse,这个是django中的一个工具
_url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) # 反向解析,args,是传入的id字段, return _url def get_delete_url(self, obj):
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,)) return _url def get_add_url(self): model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_add" % (app_label, model_name)) return _url def get_list_url(self): model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_list" % (app_label, model_name)) return _url def get_serach_conditon(self,request):
key_word = request.GET.get("q","")
self.key_word=key_word # 这是给modelstark加一个实例对象,然后在查询之后就可以直接把查询内容渲染到页面了,通过showlist.config.keyword search_connection = Q() # 默认这个是空的条件
if key_word:
# self.search_fields # ["title","price"]
search_connection.connector = "or" # 这是orm使用q查询的另外一种方法,
for search_field in self.search_fields:
search_connection.children.append((search_field + "__contains", key_word))
print("search_connection",search_connection)
return search_connection def get_filter_condition(self,request):
filter_condition=Q() for filter_field,val in request.GET.items():# courserecord=2
if filter_field !="page": # 把page这个去掉,不加入过滤
filter_condition.children.append((filter_field,val)) return filter_condition def list_view(self, request):
if request.method=="POST": # 这个post请求,就是在处理action的提交(go)
print("POST:",request.POST) # 把input框的值传过来了,把select下面的选中的值传过来,可以在post中取到action和selected_pk
action=request.POST.get("action") # patch_init
selected_pk=request.POST.getlist("selected_pk")
action_func=getattr(self,action) # 反射,从self中去找action,action这是一个变量,是对应的点击的哪一个函数
# self,是配置类,如果没有找到就去父类找,
queryset=self.model.objects.filter(pk__in=selected_pk)
ret=action_func(request,queryset) # 调用对应的函数操作, #return ret # 获取serach的Q对象
search_connection=self.get_serach_conditon(request) # 获取filter构建Q对象 filter_condition=self.get_filter_condition(request) print("search_connection",search_connection,"filter_condition",filter_condition) # 筛选获取当前表所有数据
data_list=self.model.objects.all().filter(search_connection).filter(filter_condition) # 【obj1,obj2,....】 print("data_list",data_list)
# 按这ShowList展示页面
showlist=ShowList(self,data_list,request) # 实例化一个showlist,这个self就是现在的modelstark类,需要作为一个参数传递, # 构建一个查看URL
add_url=self.get_add_url()
return render(request, "list_view.html", locals()) def extra_url(self): return [] def get_urls_2(self): temp = [] model_name=self.model._meta.model_name
app_label=self.model._meta.app_label temp.append(url(r"^add/", self.add_view,name="%s_%s_add"%(app_label,model_name))) # 这个name用来反向解析用
temp.append(url(r"^(\d+)/delete/", self.delete_view,name="%s_%s_delete"%(app_label,model_name)))
temp.append(url(r"^(\d+)/change/", self.change_view,name="%s_%s_change"%(app_label,model_name)))
temp.append(url(r"^$", self.list_view,name="%s_%s_list"%(app_label,model_name))) # 扩展url
temp.extend(self.extra_url()) return temp @property
def urls_2(self):
print(self.model)
return self.get_urls_2(), None, None class StarkSite(object):
def __init__(self):
self._registry={} def register(self,model,stark_class=None):
if not stark_class:
stark_class=ModelStark self._registry[model] = stark_class(model, self) # 括号内的两个参数,就是ModelStark默认的两个参数,self就是site def get_urls(self):
temp=[]
for model,stark_class_obj in self._registry.items():
model_name=model._meta.model_name
app_label=model._meta.app_label
# 分发增删改查
temp.append(url(r"^%s/%s/"%(app_label,model_name),stark_class_obj.urls_2)) '''
url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
url(r"^app01/book/",ModelStark(Book).urls_2), '''
return temp @property
def urls(self):
return self.get_urls(),None,None site=StarkSite()

###############  stark-分页      ###############

"""
自定义分页组件 """ class Pagination(object):
def __init__(self, current_page, all_count, base_url,params, per_page_num=8, pager_count=11, ):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param base_url: 分页中显示的URL前缀
:param pager_count: 最多显示的页码个数
""" try:
current_page = int(current_page)
except Exception as e:
current_page = 1 if current_page < 1:
current_page = 1 self.current_page = current_page self.all_count = all_count
self.per_page_num = per_page_num self.base_url = base_url # 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager self.pager_count = pager_count # 最多显示页码数
self.pager_count_half = int((pager_count - 1) / 2) import copy
params = copy.deepcopy(params)
params._mutable = True
self.params = params # self.params : {"page":77,"title":"python","nid":1} @property
def start(self):
return (self.current_page - 1) * self.per_page_num @property
def end(self):
return self.current_page * self.per_page_num def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示(11-1)/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1 # 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_start = self.all_pager - self.pager_count + 1
pager_end = self.all_pager + 1 else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1 page_html_list = []
self.params["page"] = 1
first_page = '<li><a href="%s?%s">首页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(first_page) if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
self.params["page"] = self.current_page - 1
prev_page = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(prev_page) for i in range(pager_start, pager_end):
# self.params : {"page":77,"title":"python","nid":1} self.params["page"] = i # {"page":72,"title":"python","nid":1}
if i == self.current_page:
temp = '<li class="active"><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)
else:
temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)
page_html_list.append(temp) if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
self.params["page"] = self.current_page + 1
next_page = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(next_page) self.params["page"] = self.all_pager
last_page = '<li><a href="%s?%s">尾页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(last_page) return ''.join(page_html_list) # class Pagination(object):
#
# def __init__(self, data_num, current_page, url_prefix,params, per_page=10, max_show=4):
# """
# 进行初始化.
# :param data_num: 数据总数
# :param current_page: 当前页
# :param url_prefix: 生成的页码的链接前缀
# :param per_page: 每页显示多少条数据
# :param max_show: 页面最多显示多少个页码
# """
# self.data_num = data_num
# self.per_page = per_page
# self.max_show = max_show
# self.url_prefix = url_prefix
#
# # 把页码数算出来
# self.page_num, more = divmod(data_num, per_page)
# if more:
# self.page_num += 1
#
# try:
# self.current_page = int(current_page)
# except Exception as e:
# self.current_page = 1
# # 如果URL传过来的页码数是负数
# if self.current_page <= 0:
# self.current_page = 1
# # 如果URL传过来的页码数超过了最大页码数
# elif self.current_page > self.page_num:
# self.current_page = self.page_num # 默认展示最后一页
#
# # 页码数的一半 算出来
# self.half_show = max_show // 2
#
# # 页码最左边显示多少
# if self.current_page - self.half_show <= 1:
# self.page_start = 1
# self.page_end = self.max_show
# elif self.current_page + self.half_show >= self.page_num: # 如果右边越界
# self.page_end = self.page_num
# self.page_start = self.page_num - self.max_show
# else:
# self.page_start = self.current_page - self.half_show
# # 页码最右边显示
# self.page_end = self.current_page + self.half_show
#
#
# import copy
# self.params=copy.deepcopy(params) # {"page":"12","title_startwith":"py","id__gt":"5"}
#
#
#
# @property
# def start(self):
# # 数据从哪儿开始切
# return (self.current_page - 1) * self.per_page
#
# @property
# def end(self):
# # 数据切片切到哪儿
# return self.current_page * self.per_page
#
# def page_html(self):
# # 生成页码
# l = []
# # 加一个首页
# l.append('<li><a href="{}?page=1">首页</a></li>'.format(self.url_prefix))
# # 加一个上一页
# if self.current_page == 1:
# l.append('<li class="disabled" ><a href="#">«</a></li>'.format(self.current_page))
# else:
# l.append('<li><a href="{}?page={}">«</a></li>'.format(self.url_prefix, self.current_page - 1))
#
#
#
# # {"page":"12","title_startwith":"py","id__gt":"5"} # "page=12&title_startwith=py&id__gt=5"
#
#
# print(self.params.urlencode())
# for i in range(self.page_start, self.page_end + 1):
# self.params["page"]=i # # {"page":"7","title_startwith":"py","id__gt":"5"} # "page=7&title_startwith=py&id__gt=5"
# if i == self.current_page:
# tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
# else:
# tmp = '<li><a href="{0}?{1}">{2}</a></li>'.format(self.url_prefix, self.params.urlencode(),i)
# l.append(tmp)
#
#
#
#
#
#
#
# # 加一个下一页
# if self.current_page == self.page_num:
# l.append('<li class="disabled"><a href="#">»</a></li>'.format(self.current_page))
# else:
# l.append('<li><a href="{}?page={}">»</a></li>'.format(self.url_prefix, self.current_page + 1))
# # 加一个尾页
# l.append('<li><a href="{}?page={}">尾页</a></li>'.format(self.url_prefix, self.page_num))
# return "".join(l)

###############  查看列表页面    ###############

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script> <style>
.filter a{
text-decoration: none;
color: grey;
} .active{
color: rebeccapurple!important;
}
</style>
</head>
<body> <h4>数据列表</h4> <div class="container">
<div class="row">
<div class="col-md-9">
<a href="{{ add_url }}" class="btn btn-primary">添加数据</a>
{#搜索框,只有配置了search_fields才会展示#}
{% if showlist.config.search_fields %}
{#没有写method,默认是一个get请求#}
<form action="" class="pull-right">
<input class="form-control" style="display: inline-block;width:200px" type="text" name="q" value="{{ showlist.config.key_word }}"><button class="btn btn-default">search</button>
</form>
{% endif %} {#构建这个表单,就是为了批量操作的,因为需要下面的列表数据,所以包到一起, #}
<form action="" method="post">
{% csrf_token %}
<select name="action" class="form-control" id="" style="width: 200px;margin: 8px 2px;display: inline-block;vertical-align: -1px">
<option value="">---------------</option>
{# get_action_list的结果:[{"name":""patch_init,"desc":"批量初始化"}]#}
{#每一个item就是一个字段,#}
{% for item in showlist.get_action_list %}
<option value="{{ item.name }}">{{ item.desc }}</option>
{% endfor %} </select><button type="submit" class="btn btn-success">Go</button>
<table class="table table-bordered table-striped">
{#表头#}
<thead>
<tr>
{% for item in showlist.get_header %}
<th>{{ item }}</th>
{% endfor %} </tr> </thead>
{#表数据#}
<tbody>
{% for data in showlist.get_body %} <tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %} </tbody>
</table>
<nav class="pull-right">
<ul class="pagination">
{{ showlist.pagination.page_html|safe }}
</ul>
</nav> </form>
</div> {#筛选#}
<div class="col-md-3">
{% if showlist.config.list_filter %}
<div class="filter">
<h4 style="">Filter</h4>
{% for filter_field,linktags in showlist.get_filter_linktags.items %}
<div class="well">
<p>By {{ filter_field.upper }}</p>
{% for link in linktags %}
<p>{{ link|safe }}</p>
{% endfor %}
</div>
{% endfor %} </div>
{% endif %} </div>
</div>
</div> <script> $("#choice").click(function () { if($(this).prop("checked")){
$(".choice_item").prop("checked",true)
}else {
$(".choice_item").prop("checked",false)
} }) </script>
</body>
</html>

###############  修改页面    ###############

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script> <style> input,select {
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
} .error{
color: red;
} </style>
</head>
<body> <h3>编辑页面</h3> {% include 'form.html' %} </body>
</html>

###############  删除页面    ###############

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body> <h3>删除页面</h3> <form action="" method="post">
{% csrf_token %}
<button>确认删除?</button>
<a href="{{ url }}">取消</a>
</form> </body>
</html>

###############  抽象form表单部分    ###############

<div class="container">
<div class="row">
<div class="col-md-6 col-xs-8 col-md-offset-3">
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div style="position: relative">
<label for="">{{ field.label }}</label>
{{ field }} <span class=" error pull-right">{{ field.errors.0 }}</span> {% if field.is_pop %}
{#如果是一个一对多多对多的字段,需要在字段的右侧放一个加号,需要弹出新的页面,来添加数据#}
{#position,设置标签的位置,父标签是相对定位,子标签是绝对定位,#}
{#你怎么知道一个字段是一对多多对多的字段??,根据字段的类型,如果是一对多,多对多,加一个is_pop的字段为true#}
{#绑定一个点击事件,点击要跳转到一个url,#}
<a onclick="pop('{{ field.url }}')" style="position: absolute;right: -30px;top: 20px"><span style="font-size: 28px">+</span></a>
{% endif %}
</div>
{% endfor %} <button type="submit" class="btn btn-default pull-right">提交</button>
</form>
</div>
</div>
</div>
<script>
function pop(url) {
{#点击之后弹出一个窗口,路径是传入的url,#}
window.open(url,"","width=600,height=400,top=100,left=100")
{#top=100,left=100,控制弹出窗口的位置,大小,#}
}
</script>

###############  新增页面   ###############

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script> <style> input,select {
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
} .error{
color: red;
} </style>
</head>
<body> <h3>添加页面</h3> {% include 'form.html' %} <script>
function pop_response (pk,text,id) {
{#添加内容之后,返回的时候能自动带回到页面,#}
console.log(pk,text,id); // 选择哪一个select标签
// option的文本值和value值 var $option=$('<option>'); // <option></option>
$option.html(text); // <option>南京出版社</option>
$option.val(pk); // <option value=111>南京出版社</option>
$option.attr("selected","selected") ; // <option value=111>南京出版社</option>
$("#"+id).append($option) }
</script> </body>
</html>

###############  pop页面    ###############

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body> <script>
{#这个pop_response是自己定义的#}
window.opener.pop_response('{{ res.pk }}',"{{ res.text }}",'{{ res.pop_res_id }}')
window.close()
</script> </body>
</html>

###############  admin    ###############

###############  admin    ###############

crm项目-stark组件的更多相关文章

  1. crm项目-stark组件分析

    ###############    stark组件     ################ """ 这个stark组件是非常神奇的 1,独立的一个组件 2,没有mod ...

  2. day 70 crm(7):stark组件调用,以及权限分配

    前情提要: 复习:  1: orm !!!!! 2: session 3: django 4:  前端在复习 5:  复习中间件 学习的stark 的组件调用,以及权限的应用 一:权限的概念,  1: ...

  3. crm 使用stark组件

    # Create your models here. from django.db import models class Department(models.Model): "" ...

  4. day67 crm(4) stark组件的增删改 以及 model_from使用和from组件回顾

        前情提要:Django  stark 组件开发的 增删改,  model_form组件的使用 form组件的回顾 一:list_display_link  创建 功能描述:   使包含的字段能 ...

  5. crm项目-权限组件

    ###############    表结构分析     ################ """ 表结构设计: 1,四张表 用户表,userinfo,这个表本身不会被创 ...

  6. CRM项目之stark组件

    . stark也是一个app(用startapp stark创建),目标时把这个做成一个可以拔插的组件 . setting文件下INSTALLED_APPS 路径要配置好(app的注册) . 写好si ...

  7. CRM项目之stark组件(2)

    那么从今天开始呢,我们就要开始设计属于我们自己的admin组件,起个名字就叫stark吧(当然你愿意叫什么都可以). stark组件之四步走 仿照admin组件实现流程,stark组件要实现四件事情: ...

  8. crm项目之stark组件前戏(二)

    stark组件的设计主要来源于django中admin的功能,在django admin中只需要将模型表进行注册,就可以在页面对该表进行curd的动作,那么django admin是如何做的呢? 在d ...

  9. CRM项目之RBAC权限组件-day26

    写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...

随机推荐

  1. Linux--Centos7开启关闭端口

    参考 http://blog.csdn.net/u013410747/article/details/61696178 查看已开放的端口(默认不开放任何端口)    firewall-cmd --li ...

  2. 18 11 15 网络通信 ---- 多任务----线程 threading

    下面是一个  多线程  运算  调用了 threading  模块   可以同时在一个程序中  跑两个函数 import threading def text1 (): for i in range( ...

  3. 视图家族之视图工具集viewsets

    视图家族之视图工具集viewsets 一.视图集ViewSet 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中: list() 提供一组数据 retrieve() 提供单个数据 cr ...

  4. Springboot整合Junit单元测试

    1.在pom.xml中添加junit环境的依赖 <dependency> <groupId>org.springframework.boot</groupId> & ...

  5. php IP地址转换

    <?php $enip = ip2long('210.110.11.49); echo $enip."<br />";//-764540111 echo long ...

  6. sourceTree 代码回滚(git 和http)

    近些时候,有遇到提交后代码有误的情况,所以需要回退到前一个版本.因为不常见,所以每次都不是很熟练,记录于此,以备查阅. 一.[将master重置到这次提交] 在sourceTree中选中错误的提交的下 ...

  7. PAT Advanced 1084 Broken Keyboard (20) [Hash散列]

    题目 On a broken keyboard, some of the keys are worn out. So when you type some sentences, the charact ...

  8. 第二季 第十一天 part2

    const greeting = function() { // 注意,这个 this.name 取决于谁调用了 greeting() 函数 console.log('Hi, ', this.name ...

  9. 【转】我们为什么要使用 Markdown

    目录 从前码字时我们面临着什么困境 标记语言显神威 到底什么是 Markdown 所以为什么我们要使用 Markdown Markdown 简明语法 段落和换行 标题 区块引用 列表 强调 代码标识和 ...

  10. 哈夫曼编码的理解(Huffman Coding)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...