- 1、效果图
- 2、详细步骤解析
- 3、总结、代码
1、效果图
增
删除
改
2、详细步骤解析
1、构造增删改查url,反向解析
2、ModelForm定制add、edit页面
3、starak中的ModelForm
3、总结、代码
1、知识点
1.解决代码重用
{% include 'form.html' %} 2.自定制配置modelform
每张表,就可自定义配置 labels , widges...
class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__"
labels = {
"title": '书籍名称',
"price": '价格',
}
...
modelform_class = BookModelForm
3、stark中的Modelform配置
modelform_class = []
# ModelForm组件渲染 list、增、删、改页面
def get_modelform_class(self):
"""ModelForm组件"""
if not self.modelform_class:
from django.forms import ModelForm
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class
配置样式,由于不确定字段,得在前端玩!
4.change_view()
注意 instance,否则为添加
form = ModelFormDemo(request.POST, instance=edit_obj)
if form.is_valid():
form.save()
2、模板层代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block title %}
<title>Title</title>
{% endblock %} <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
<script src="/static/jQuery/jquery-3.2.1.min.js"></script>
{% block css %} {% endblock %}
</head> <body>
<div class="container">
<div class="row">
{% block header %} {% endblock %} <div class="col-md-9 col-md-offset-1">
{% block content %} {% endblock %}
</div>
</div>
</div>
{% block javascript %} {% endblock %}
</body>
</html>
base.html
{% extends 'base.html' %} {% block title %}
<title>add页面</title>
{% endblock %} {% block css %}
<style type="text/css">
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>
{% endblock %} {% block header %}
<h3>add页面</h3>
{% endblock %} {% block content %}
{% include 'form.html' %}
{% endblock %}
add_view.html
{% extends 'add_view.html' %} {% block title %}
<title>edit页面</title>
{% endblock %} {% block header %}
<h3>edit页面</h3>
{% endblock %}
change_view.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>删除页面</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
<script src="/static/jQuery/jquery-3.2.1.min.js"></script>
</head> <body>
<div class="container"> <form action="" method="post" class="text-center">
{% csrf_token %}
<p class="text-info">你确认要删除这条记录?</p>
<button class="btn btn-danger">确认</button>
<a href="{{ url }}" class="btn btn-primary">取消</a>
</form> </div>
</body>
</html>
delete_view.html
<form action="" method="post" novalidate>
{% for field in form %}
{% csrf_token %}
<div class="form-group">
<label for="">{{ field.label }}</label>
{{ field }}
<span class="error pull-right">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<br>
<button class="btn btn-success pull-right">提交</button>
</form>
form.html
{% extends 'base.html' %} {% block title %}
<title>list页面</title>
{% endblock %} {% block header %}
<h3>list页面</h3>
{% endblock %}
{% block content %}
<a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
<table class="table table-bordered table-striped">
<tr>
{% for header in header_list %}
<th>{{ header }}</th>
{% endfor %}
</tr> {% for data in new_data_list %}
<tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %}
</table>
{% endblock %} {% block javascript %}
<script type="text/javascript">
$('#choice').click(function () {
if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
$('.choice_item').prop("checked", true)
} else {
$('.choice_item').prop("checked", false)
}
})
</script>
{% endblock %}
list_view.html
3、stark/service/stark.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 ModelStark(object):
list_display = ["__str__"] # 子类中没有,直接用父类自己的
list_display_links = [] modelform_class = [] def __init__(self,model, site):
self.model = model
self.site = site # 增删改查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 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'>") def edit(self,obj=None, header=False):
if header:
return "操作"
# 方案1:固定url
# return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
# 方案2:拼接url
# return mark_safe("<a href='%s/change'>编辑</a>") # 方案3:反向解析
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
_url = reverse("%s_%s_change"%(app_label,model_name),args=(obj.pk,))
# print("_url",_url)
return mark_safe("<a href='%s'>编辑</a>"%_url) def deletes(self,obj=None, header=False):
if header:
return "操作"
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 mark_safe("<a href='%s'>删除</a>"%_url) # ModelForm组件渲染 list、增、删、改页面
def get_modelform_class(self):
"""ModelForm组件"""
if not self.modelform_class:
from django.forms import ModelForm
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class def new_list_play(self):
"""构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
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 list_view(self, request):
print(self.model) # <class 'app01.models.Book'> 用户访问的模型表 # 构建表头
header_list = [] # # header_list = ['选择','pk',...'操作','操作']
for field in self.new_list_play():
if callable(field):
# header_list.append(field.__name__)
val = field(self,header=True)
header_list.append(val)
else:
if field == "__str__":
header_list.append(self.model._meta.model_name.upper())
else:
val = self.model._meta.get_field(field).verbose_name # 中文名称
header_list.append(val) # 构建表单
data_list = self.model.objects.all() # [obj1,obj2,...]
new_data_list = []
for obj in data_list: # Book表模型,Author表模型
temp = []
for field in self.new_list_play(): # ['name','age']
if callable(field): # edit() 可调用的
val = field(self,obj) # 直接调用edit()函数
print('val--------->',val)
else:
val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮
if field in self.list_display_links:
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
_url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
# print(_url)
val = mark_safe("<a href='%s'>%s</a>"%(_url,field)) temp.append(val) new_data_list.append(temp) print('new_data_list',new_data_list) # 构造数据 [['jack', 44], ['mark', 33]] # 构建一个addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals()) def add_view(self, request):
ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo()
if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "add_view.html",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):
edit_obj = self.model.objects.filter(pk=id).first() ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo(instance=edit_obj)
if request.method == "POST":
form = ModelFormDemo(request.POST,instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "change_view.html",locals()) def get_urls2(self):
"""构造 add/delete/change"""
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label temp = []
temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
temp.append(url(r'^add/', self.add_view, name='%s_%s_add'%(app_label,model_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))) return temp @property
def urls2(self): return self.get_urls2(), None, None class StarkSite(object):
"""site单例类"""
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) def get_urls(self):
"""构造一层urls app01/book"""
temp = []
for model, stark_class_obj in self._registry.items():
print(model, 'stark_clas_obj', stark_class_obj) # 不同的model模型表
"""
<class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
<class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
""" app_label = model._meta.app_label # app01
model_name = model._meta.model_name # book
# temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
"""
path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
path('app01/book/',ModelStark(Book,site).urls2),
""" return temp @property
def urls(self): # return [],None,None
return self.get_urls(),None,None site = StarkSite() # 单例对象
4、app01下的stark.py
from stark.service import stark
from .models import *
from django.forms import ModelForm class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__" labels = {
"authors":"作者",
"publishDate":"出版日期",
} class BookConfig(stark.ModelStark):
list_display = ['nid', 'title', 'price']
modelform_class = BookModelForm class AuthorConfig(stark.ModelStark):
list_display = ['nid', 'name', 'age']
list_display_links = ['name','age'] stark.site.register(Book,BookConfig)
stark.site.register(Publish)
stark.site.register(Author,AuthorConfig)
stark.site.register(AuthorDetail) print(stark.site._registry) """
{<class 'app01.models.Book'>: <stark.service.stark.ModelStark object at 0x0000003AA7439630>,
<class 'app01.models.Publish'>: <stark.service.stark.ModelStark object at 0x0000003AA7439668>,
<class 'app01.models.Author'>: <stark.service.stark.ModelStark object at 0x0000003AA74396A0>,
<class 'app01.models.AuthorDetail'>: <stark.service.stark.ModelStark object at 0x0000003AA7439940>}
"""
附上核心代码注释:
增加页面(利用modelForm):
#1.首先定义一个方法,如果modelForm是自定制的话,就可以去用户自定制的
def get_modelform_class(self):
if not self.modelform_class: #如果不是自定制的话,那么就使用默认的。
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class #不论是哪个都需要返回。
2.admin中自定制:
class ModelFormDemo(ModelForm):
class Meta:
model = Book
fields = "__all__"
labels = {
"title": "书籍名称",
"price": "价格"
}
class BookConfig(ModelStark):
list_display = ["title","price","publishDate"]
modelform_class = ModelFormDemo
3. 增加的函数:
def add_view(self,request):
ModelFormDemo=self.get_modelform_class() #取到ModelFormDemo
if request.method=="POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save() #如果是POST请求表示添加,从request.POST取到数据,直接添加即可。
return redirect(self.get_list_url())
else: #字段填写错误,在前端利用{{form.errors.0}}显示出来。页面不会刷新。
return render(request, "add_view.html", locals())
} form = ModelFormDemo()
return render(request,"add_view.html",locals())
4.编辑页面
#和增加同理,只是利用ID找到这条数据对象,加一个instarce=数据对象,即可改为更新操作。而不是增加
def change_view(self,request,id):
ModelFormDemo = self.get_modelform_class()
edit_obj = self.model.objects.filter(pk=id).first()
if request.method=="POST":
form = ModelFormDemo(request.POST,instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
else:
return render(request, "add_view.html", locals()) form = ModelFormDemo(instance=edit_obj)
return render(request,"change_view.html",locals())
5.删除页面:
#首先点击按钮后是跳转到一个确认页面,发的是post请求表示确认删除,如果点击a标签的取消表示返回到原来页面。
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())