一、url的分发练习
from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import HttpResponse
def index(request):
return HttpResponse("首页")
def add(request): #add视图函数
return HttpResponse("add")
def list_view(request): #list_view视图函数
return HttpResponse("list_view")
def change(request,id): #change视图函数
return HttpResponse("change")
def delete(request,id): #delete视图函数
return HttpResponse("delete")
def get_urls2(): #url的二级分发函数
temp=[
url("^add/$",add),
url("^$",list_view),
url("^(\d+)/change/$",change),
url("^(\d+)/delete/$",delete),
]
return temp
def get_urls():
temp=[]
for model,model_class_obj in admin.site._registry.items(): # 模型类:该模型类的配置类对象 {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....}
app_name=model._meta.app_label #得到应用名
model_name=model._meta.model_name
temp.append(url(r"%s/%s/"%(app_name,model_name),(get_urls2(),None,None))) #url做分发,后面跟元组,元组第一项为一个列表
return temp
from stark.service.sites import site
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r"^stark",(get_urls(),None,None))
]
二、实现stark组件
app01应用的models.py文件:
from django.db import models
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
age=models.IntegerField()
def __str__(self):
return self.name
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField()
def __str__(self):
return self.name
class Book(models.Model):
nid = models.AutoField(primary_key=True,verbose_name="编号")
title = models.CharField( max_length=32,verbose_name="名称")
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 与Publish建立一对多的关系,外键字段建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
authors=models.ManyToManyField(to='Author',)
def __str__(self):
return self.title
#执行下面python语句生成相关表(数据迁移)
# python3 manage.py makemigrations
# python3 manage.py migrate
项目下的settings.py文件设置:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
"app02.apps.App02Config",
"stark.apps.StarkConfig",
]
STATIC_URL = '/static/'
STATICFILES_DIRS=[
os.path.join(BASE_DIR,"static")
]
项目的urls.py文件:
from django.conf.urls import url
from django.contrib import admin
from stark.service.sites import site
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^stark/', site.urls), #模拟admin的实现方式,在stark目录后面进行分发
]
app01应用的stark.py文件对app01的应用表进行注册:
from stark.service.sites import site,ModelStark
from app01.models import Book
from app01.models import Publish
from app01.models import Author
class BookConfig(ModelStark):
# def display_authors(self, obj=None,is_header=False): #显示多对多字段,单独定义函数实现方式
#
# if is_header:
# return "作者"
# s=[]
# for author in obj.authors.all():
# s.append(author.name)
#
# return " ".join(s)
list_display = ["nid","title","price","publish","authors",]
# list_display = ["nid","title","price","publish",display_authors]
site.register(Book,BookConfig)
site.register(Publish)
site.register(Author)
项目下的stark目录下apps.py定义执行各个应用的stark.py:
from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class StarkConfig(AppConfig):
name = 'stark'
def ready(self):
autodiscover_modules('stark') # 执行每一个app下的stark.py
项目下的stark目录下service目录下sites.py定义对用户访问url的分发:
from django.conf.urls import url
from django.shortcuts import HttpResponse, render
from django.utils.safestring import mark_safe
class ModelStark(): #将增,删,改,查写到ModelStark类中,这样谁调用类中的功能,self.model就是用户访问的表
list_display = ["__str__", ]
def __init__(self, model, site):
self.model = model
self.site = site
def edit(self, obj=None, is_header=False):
if is_header:
return "操作" #表头返回 "操作"
return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk) #mark_safe会识别返回的html标签
def delete(self, obj=None, is_header=False):
if is_header:
return "操作"
return mark_safe("<a href='%s/delete'>删除</a>" % obj.pk)
def checkbox(self, obj=None, is_header=False):
if is_header:
return "选择"
return mark_safe("<input type='checkbox' pk=%s>" % obj.pk) #在对应位置显示多选框
def add(self, request):
return HttpResponse("add")
def new_list_display(self): #新的显示样式,这样所有表的显示都有多选框,编辑和删除操作
temp = []
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
temp.append(ModelStark.edit)
temp.append(ModelStark.delete)
return temp
def list_view(self, request):
print(self.model)
data_list = self.model.objects.all()
print("list_display", self.list_display) # ["nid","title","price",edit]
# 处理表头
header_list = []
for field in self.new_list_display():
if isinstance(field, str): #判断field是字符串类型
if field == "__str__": #字段是__str__
val = self.model._meta.model_name.upper() #表头显示表名的大写字母
else:
field_obj = self.model._meta.get_field(field)
val = field_obj.verbose_name #得到字段的verbose_name,定义后可以显示中文
else:
val = field(self, is_header=True) #field是函数,执行函数
header_list.append(val)
# 处理表单数据
new_data_list = []
for obj in data_list:
temp = []
for field in self.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"]
if isinstance(field, str):
try:
from django.db.models.fields.related import ManyToManyField
field_obj = self.model._meta.get_field(field) #得到field的字段对象
if isinstance(field_obj, ManyToManyField): #判断是多对多关系的字段
l = []
for i in getattr(obj, field).all(): #.all()得到所有的对象,否则none
l.append(str(i))
val = ",".join(l)
else:
val = getattr(obj, field)
print("val", val)
except Exception as e:
val = getattr(obj, field) #反射,取到字段名
else:
val = field(self, obj)
temp.append(val)
new_data_list.append(temp)
return render(request, "list_view.html", locals())
def change(self, request, id):
return HttpResponse("change")
def delete_view(self, request, id):
return HttpResponse("delete_view")
def get_urls2(self):
temp = [
url("^add/$", self.add),
url("^$", self.list_view),
url("^(\d+)/change/$", self.change),
url("^(\d+)/delete/$", self.delete_view),
]
return temp
@property
def urls2(self):
return self.get_urls2(), None, None
class StarkSite():
def __init__(self, ):
self._registry = {}
# 一级分发
def get_urls(self):
temp = []
for model, model_class_obj in self._registry.items(): # {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....}
app_name = model._meta.app_label
model_name = model._meta.model_name
temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2)) #接着二级分发
return temp
@property
def urls(self):
return self.get_urls(), None, None
def register(self, model, admin_class=None, **options):
if not admin_class:
admin_class = ModelStark
self._registry[model] = admin_class(model, self)
site = StarkSite()
list_view.html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bs/css/bootstrap.css">
</head>
<body>
<h3>查看数据</h3>
<div>
<div>
<div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
{% for foo in header_list %}
<th>{{ foo }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for new_data in new_data_list %}
<tr>
{% for foo in new_data %}
<td>{{ foo }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
三、显示多对多字段的另一种方法
stark.py注册表时自定义函数:
class BookConfig(ModelStark):
def display_authors(self, obj=None,is_header=False): #显示多对多字段
if is_header:
return "作者"
s=[]
for author in obj.authors.all():
s.append(author.name)
return " ".join(s)
list_display = ["nid","title","price","publish",display_authors]
sites.py里面的ModelStark类定义的list_view
def list_view(self, request):
print(self.model)
data_list = self.model.objects.all()
print("list_display", self.list_display) # ["nid","title","price",edit]
# 处理表头
# header_list=["ID","名称","价格"]
header_list=[]
for field in self.new_list_display():
if isinstance(field,str):
if field=="__str__":
val=self.model._meta.model_name.upper()
else:
field_obj=self.model._meta.get_field(field)
val=field_obj.verbose_name
else:
val=field(self,is_header=True)
header_list.append(val)
# 处理表单数据
new_data_list = []
for obj in data_list:
temp = []
for field in self.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"]
if isinstance(field,str):
val = getattr(obj, field)
else:
val=field(self,obj)
temp.append(val)
new_data_list.append(temp)
页面显示效果图:
四、stark组件自定义功能设置
app01应用下的stark.py文件:
from stark.service.sites import site,ModelStark
from app01.models import Book
from app01.models import Publish
from app01.models import Author
class BookConfig(ModelStark):
def display_authors(self, obj=None,is_header=False):
if is_header:
return "作者"
s=[]
for author in obj.authors.all():
s.append(author.name)
return " ".join(s)
list_display = ["nid","title","price","publish","authors",] #自定义显示的字段
search_fields=["title","price"] #搜索依据的字段
def patch_init(self,selected_pk):
print("selected_pk",selected_pk)
ret=self.model.objects.filter(pk__in=selected_pk).update(price=0)
print("====>",ret)
patch_init.desc="批量初始化"
def patch_delete(self,selected_pk):
print("selected_pk",selected_pk)
ret=self.model.objects.filter(pk__in=selected_pk).delete()
print("====>",ret)
patch_delete.desc="批量删除"
actions=[patch_init,patch_delete] #定义批量操作
site.register(Book,BookConfig)
site.register(Publish)
site.register(Author)
stark组件下service目录sites.py文件进行完善:
from django.conf.urls import url
from django.shortcuts import HttpResponse, render, redirect
from django.utils.safestring import mark_safe
from django.urls import reverse
class Show_List(object):
def __init__(self, config, data_list):
self.config = config
self.data_list = data_list
def get_header(self):
# 处理表头
# header_list=["ID","名称","价格"]
header_list = []
for field in self.config.new_list_display():
if isinstance(field, str):
if field == "__str__":
val = self.config.model._meta.model_name.upper()
else:
field_obj = self.config.model._meta.get_field(field)
val = field_obj.verbose_name
else:
val = field(self.config, is_header=True)
header_list.append(val)
return header_list
def get_body(self):
# 处理表单数据
new_data_list = []
for obj in self.data_list:
temp = []
for field in self.config.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"]
if isinstance(field, str):
try:
from django.db.models.fields.related import ManyToManyField
field_obj = self.config.model._meta.get_field(field)
if isinstance(field_obj, ManyToManyField):
l = []
for i in getattr(obj, field).all():
l.append(str(i))
val = ",".join(l)
else:
val = getattr(obj, field)
print("val", val)
except Exception as e:
val = getattr(obj, field)
else:
val = field(self.config, obj)
temp.append(val)
new_data_list.append(temp)
return new_data_list
def get_new_actions(self):
action_list = []
for i in self.config.actions: # [patch_init,]
action_list.append({
"desc": i.desc,
"name": i.__name__,
})
return action_list
class ModelStark(): # 功能的样式显示类
list_display = ["__str__", ]
search_fields = []
actions = []
def __init__(self, model, site):
self.model = model
self.site = site
def edit(self, obj=None, is_header=False):
if is_header:
return "操作"
return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
def delete(self, obj=None, is_header=False):
if is_header:
return "操作"
return mark_safe("<a href='%s/delete'>删除</a>" % obj.pk)
def checkbox(self, obj=None, is_header=False):
if is_header:
return "选择"
return mark_safe("<input type='checkbox' name='selected_pk' value=%s>" % obj.pk)
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 new_list_display(self):
temp = []
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
temp.append(ModelStark.edit)
temp.append(ModelStark.delete)
return temp
def get_search_condition(self, request): #定义搜索查找函数
from django.db.models import Q
search_condition = Q()
val = request.GET.get("q")
if val:
search_condition.connector = "or" #设置搜索依据的字段是或者的关系,即满足一个字段的查找结果就可以
for field in self.search_fields:
search_condition.children.append((field + "__contains", val)) #搜索的字符串进行模糊匹配
return search_condition
def list_view(self, request):
if request.method == "POST":
action = request.POST.get("action")
selected_pk = request.POST.getlist("selected_pk")
action = getattr(self, action)
action(selected_pk)
search_condition = self.get_search_condition(request)
data_list = self.model.objects.all().filter(search_condition)
print("list_display", self.list_display) # ["nid","title","price",edit]
sl = Show_List(self, data_list)
return render(request, "list_view.html", locals())
def get_mdoelForm(self):
from django.forms import ModelForm
class DemoModelForm(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return DemoModelForm
def add(self, request): #定义添加页面的函数
if request.method == "POST":
form = self.get_mdoelForm()(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
else:
return render(request, "add.html", locals())
form = form = self.get_mdoelForm()()
return render(request, "add.html", locals())
def change(self, request, id): #定义编辑函数
obj = self.model.objects.filter(pk=id).first()
if request.method == "POST":
form = self.get_mdoelForm()(request.POST, instance=obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
form = self.get_mdoelForm()(instance=obj)
return render(request, "change.html", locals())
def delete_view(self, request, id):
if request.method == "POST":
self.model.objects.get(pk=id).delete()
return redirect(self.get_list_url())
url = self.get_list_url()
return render(request, "delete.html", locals())
def get_urls2(self):
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
temp = [
url("^add/$", self.add, name="%s_%s_add" % (app_label, model_name)),
url("^$", self.list_view, name="%s_%s_list" % (app_label, model_name)),
url("^(\d+)/change/$", self.change, name="%s_%s_change" % (app_label, model_name)),
url("^(\d+)/delete/$", self.delete_view, name="%s_%s_delete" % (app_label, model_name)),
]
return temp
@property
def urls2(self):
return self.get_urls2(), None, None
class StarkSite():
def __init__(self, ):
self._registry = {}
# 一级分发
def get_urls(self):
temp = []
for model, model_class_obj in self._registry.items():
app_name = model._meta.app_label
model_name = model._meta.model_name
temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2))
return temp
@property
def urls(self):
return self.get_urls(), None, None
def register(self, model, admin_class=None, **options):
if not admin_class:
admin_class = ModelStark
self._registry[model] = admin_class(model, self)
site = StarkSite()
templates模板
form.html页面:
<div>
<div>
<div class="col-md-8 col-md-offset-1">
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div>
<label for="">{{ field.label }}</label>
{{ field }} <span style="color: red">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<input type="submit" class="btn btn-default">
</form>
</div>
</div>
</div>
add.html添加页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bs/css/bootstrap.css">
<style>
input[id], 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;
}
</style>
</head>
<body>
<h3>添加页面</h3>
{% include 'form.html' %}
</body>
</html>
change.html修改页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bs/css/bootstrap.css">
<style>
input[id], 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;
}
</style>
</head>
<body>
<h3>编辑页面</h3>
{% include 'form.html' %}
</body>
</html>
delete.html删除页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bs/css/bootstrap.css">
</head>
<body>
<h3>删除页面</h3>
<form action="" method="post">
{% csrf_token %}
<input type="submit" value="确认删除">
<a href="{{ url }}">取消</a>
</form>
</body>
</html>
list_view.html显示页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bs/css/bootstrap.css">
<style>
.search {
margin: 20px;
}
</style>
</head>
<body>
<h3>查看数据</h3>
<a href="add/" class="btn btn-primary">添加数据</a>
<div>
<div>
<div>
<form action="" class="search pull-right" method="get">
<input type="text" name="q" style="width: 300px;display: inline-block">
<button class="btn btn-danger">search</button>
</form>
<form action="" method="post">
{% csrf_token %}
<select name="action" id="" style="width: 200px;display: inline-block">
{% for action_dict in sl.get_new_actions %}
<option value="{{ action_dict.name }}">{{ action_dict.desc }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-success">Go</button>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
{% for foo in sl.get_header %}
<th>{{ foo }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for new_data in sl.get_body %}
<tr>
{% for foo in new_data %}
<td>{{ foo }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
页面效果图:
转载于:https://blog.51cto.com/qidian510/2129950