django进阶-3
先看效果图:
登陆admin后的界面:
查看作者:
当然你也可以定制admin, 使界面更牛逼
数据库表结构: app01/models.py
from django.db import models
from django.utils.html import format_html #把字符串变成html # Create your models here.
class Author(models.Model):
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)
email = models.EmailField() def __str__(self):
return "<%s %s>" % (self.first_name,self.last_name) class Meta:
verbose_name_plural = u"作者" class Publisher(models.Model):
name = models.CharField(max_length=64, unique=True)
address = models.CharField(max_length=128,null=True,blank=True)
city = models.CharField(max_length=64)
state_province = models.CharField(max_length=64,help_text="put your province here",verbose_name=u"所属省")
country = models.CharField(max_length=64,editable=False)
website = models.URLField() def __str__(self):
return "<%s>" % (self.name) class Book(models.Model):
name = models.CharField(max_length=128)
authors = models.ManyToManyField(Author) #书多对多到作者
publisher = models.ForeignKey(Publisher) #一对多
publish_date = models.DateField() #精确到天DateField()
status_choices = (("published", u"已出版"),
("producing", u"待出版"),
("forbidden", u"禁书"),
)
# 此时应该给个默认值,给之前没有status字段的书。
status = models.CharField(choices=status_choices, max_length=32, default="producing") def __str__(self):
return "<%s %s>" % (self.name,self.publisher) def colored_status(self):
if self.status == "published":
format_td = format_html("<span style='padding:2px;background-color:yellowgreen'>已出版</span>")
elif self.status == "producing":
format_td = format_html("<span style='padding:2px;background-color:red'>待出版</span>")
elif self.status == "forbidden":
format_td = format_html("<span style='padding:2px;background-color:yellow'>禁书</span>") return format_td colored_status.short_description = "STATUS" #页面显示为colored_status即方法名,这里改名为STATUS
现在你看到我直接贴代码,肯定不爽。好吧……
首先上面有三张表: Author(作者表)、Publisher(出版社表)、Book(图书表)。表与表的关联也很简单,一本书可由多个作者联合出,一个作者可出多本书,书与作者为ManyToMany关系;一本书只能由一个出版社出版,一个出版社可出多本书,一对多,用外键ForeignKey关联。
其它的__str__是啥?verbose_name是毛线东西? 看我之前的博客咯。
你登陆admin后其实是看不到3张表的,需要在admin.py注册一下:
from app01 import models admin.site.register(models.Author)
admin.site.register(models.Book, BookAdmin)
admin.site.register(models.Publisher)
注册后再刷新页面,便可以看见表了。
一、form表单定制
在django进阶-1已经有下面这张图了,当你输入为空时,django会出现下面的error提示。
但现在你前端玩得很6,你觉得django自己的form表单so uglily,你想自己做个form表单(可用bootstrap美化),但又希望你做的表单有django的验证功能(重要!!)。so, How to do it?? 下面来自定制创建图书的form表单。
第一步: 创建form类
你定制的form表单可能有很多,应该建一个forms.py文件来存放定制的表单。
接下来在forms.py导入forms, 创建BookForm类(也可以命名为别的~)
from django import forms
from app01 import models class BookForm(forms.Form):
name = forms.CharField(max_length=10)
# publisher_id = forms.IntegerField(widget=forms.Select)
publish_date = forms.DateField()
第二步: 处理用户请求
用户最开始请求数据是GET方式, 当输入数据后修改数据(创建图书),提交方式为POST
def book_form(request):
form = forms.BookForm() # 生成form实例
if request.method == "POST":
print(request.POST)
form = forms.BookForm(request.POST)
if form.is_valid(): #进行验证
print("form is ok")
print(form)
print(form.cleaned_data) #{'name': 'qq', 'publish_date': datetime.date(2017, 3, 14)}
form_data = form.cleaned_data
form_data["publisher_id"] = request.POST.get("publisher_id")
book_obj = models.Book(**form_data) #form_data为字典形式
book_obj.save()
else:
print(form.errors)
publisher_list = models.Publisher.objects.all() return render(request, "app01/book_form.html", {"book_form":form,
"publishers":publisher_list})
当用户发起GET请求时,要生成一个空的form实例,并从数据库中查找所有的出版社publisher_list,之后进行渲染render. 接下来当然得写book_form.html啦。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="POST">{% csrf_token %}
{{ book_form }}
<select name="publisher_id">
{% for publisher in publishers %}
<option value="{{ publisher.id }}">{{ publisher.name }}</option>
{% endfor %}
</select>
<input type="submit" value="创建图书"/>
</form>
</body>
</html>
要是上面看不懂了,就别往下看了……可以看下我之前的博客哈。根据上面的html,会出现如下界面:
当你输入书名等信息,再点创建图书时,此时是以POST方式发起请求。
我们要将数据发给django强大的form表单进行验证(你可能没有输入或者日期输入为SB), 这些属于前端的验证,前端的验证是为了减轻后台服务器的压力。只需将请求的数据request.POST传给forms.py的BookForm()即可。
form = forms.BookForm(request.POST)
此时我们还需要进行后台验证,有可能成功,also可能失败。当验证成功时,form.is_valid返回true.
if form.is_valid(): #进行验证
验证成功后,自然是获取数据,存到数据库创建图书啦。好,信息是封装在form实例的,现打印form:
Print(form) <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" maxlength="10" name="name" type="text"
value="zcl_papa" required /></td></tr>
<tr><th><label for="id_publish_date">Publish date:</label></th><td><input id="id_publish_date" name="publish_
date" type="text" value="2017-03-14" required /></td></tr>
擦,一堆html
要获取干净的数据,需处理一下:
form_data = form.cleaned_data
Print(form.cleaned_data) {'name': 'zcl_papa', 'publish_date': datetime.date(2017, 3, 14)}
form表单定制ending.
这里有个问题,为啥要在BookForm去掉publisher_id字段??
因为无法直接获取出版社的信息(下拉列表为空的),要想在前端界面有供选择出版社的input标签,需要自己在html添加
<select name="publisher_id">
{% for publisher in publishers %}
<option value="{{ publisher.id }}">{{ publisher.name }}</option>
{% endfor %}
</select>
最后还需要将获得的信息加到字典(干净的数据)中,再添加到数据库。
呵呵,这比较麻烦,下面介绍更优化的方法。
modelform
为了解决前面无法获取publisher_id的问题,引入modelform
modelform与form有很多相似之处的。接下来用modelform做个前端表单,当然,会丑点……
第一步:
在forms.py创建类,继承forms.ModelForm:
可绑定Book表,Book表有什么字段,form表单就有什么字段,当然你也可以用fields使想显示的字段显示在界面。
class BookModelForm(forms.ModelForm): class Meta:
model = models.Book #绑定Book类
#fields = {"name", "publish_date"} #只包括name,publish-date字段
exclude = () #代表所有字段都包括
widgets = {
# 可以定义css样式,牛逼啊
"name": forms.TextInput(attrs={"class":"form-control"}),
}
第二步: 处理用户请求
def book_modelform(request):
form = forms.BookModelForm
print(request.POST)
if request.method == "POST":
form = forms.BookModelForm(request.POST)
if form.is_valid(): # 进行验证
print("form is ok")
print(form)
print(form.cleaned_data) # {'name': 'qq', 'publish_date': datetime.date(2017, 3, 14)}
form.save() return render(request, "app01/book_modelform.html", {"book_form":form})
第三步: 写html模版,book_modelform.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.form-control{
color: red;
}
</style>
</head>
<body>
<form action="" method="post">{% csrf_token %}
{{ book_form }}
<input type="submit" value="创建新书"/>
</form> </body>
</html>
效果图:
app01/forms.py
from django import forms
from app01 import models class BookForm(forms.Form):
name = forms.CharField(max_length=10)
# publisher_id = forms.IntegerField(widget=forms.Select)
publish_date = forms.DateField() class BookModelForm(forms.ModelForm): class Meta:
model = models.Book #绑定Book类
#fields = {"name", "publish_date"} #只包括name,publish-date字段
exclude = () #代表所有字段都包括
widgets = {
# 可以定义css样式,牛逼啊
"name": forms.TextInput(attrs={"class":"form-control"}),
}
二、admin定制
费话不多说,先上效果图:
第一次看到这界面效果,卧槽,amazing....
django的admin后台可以定制成上面的形式,当然你也可以自己定制得更漂亮。
在admin.py加上一个继承admin.ModelAdmin的类
class BookAdmin(admin.ModelAdmin): #定制book,需将类当作参数传给admin
# list_display不能显示多对多的,比如authors:
# (admin.E109) The value of 'list_display[2]' must not be a ManyToManyField.
list_display = ("id","name", "publisher","publish_date","colored_status","status") #定制为三列 search_fields = ("name", "publisher__name") #__表示出版社关联到名字
list_filter = ("publisher", "publish_date") #过滤
list_editable = ("name", "publish_date") #可修改
list_per_page = 10 #每页显示数量
#即便只有一个值也要加逗号,不然就不当成元组了
#The value of 'filter_horizontal' must be a list or tuple.
filter_horizontal = ("authors",) #选择作者时进行定制 PS:用于多对多关联
raw_id_fields = ("publisher",) #选择出版社时进行定制 PS:用于FK外键关联 actions = [make_forbidden]
定制后完,需将类当作参数传给admin:
admin.site.register(models.Book, BookAdmin)
定制作者与出版社的效果图:
ok, 现在有个新需求,想在book界面有个可以选择书出版或未出版的功能,如何实现呢? 而且可以给界面的已出版/未出版加上颜色样式??
首先你要给book表加上一个新的字段:
status_choices = (("published", u"已出版"),
("producing", u"待出版"),
("forbidden", u"禁书"),
)
# 此时应该给个默认值,给之前没有status字段的书。
status = models.CharField(choices=status_choices, max_length=32, default="producing") def __str__(self):
return "<%s %s>" % (self.name,self.publisher)
再将status字段加到list_display,就能显示在界面上了。so easy.
如何实现上图的颜色呢??
在models.py下的Book类(用于创建Book表),定义colored_status方法(也可定义为别的名~) 加入下面代码:
def colored_status(self):
if self.status == "published":
format_td = format_html("<span style='padding:2px;background-color:yellowgreen'>已出版</span>")
elif self.status == "producing":
format_td = format_html("<span style='padding:2px;background-color:red'>待出版</span>")
elif self.status == "forbidden":
format_td = format_html("<span style='padding:2px;background-color:yellow'>禁书</span>") return format_td colored_status.short_description = "STATUS" #页面默认显示为colored_status即方法名,这里改名为STATUS
自我感觉注释得挺明白的。对不同的status判断,并返回不同的css样式。
这里注意导入format_html,可将字符串变成对应html
from django.utils.html import format_html #把字符串变成html
admin action
需求又来了……
批量修改书的status,如将选中所有的书全都修改为禁书。
上图的Action下拉框默认只有Delete selected books,如何才能使下拉框能Set to forbidden选项?? 实现选择forbidden再点击Go,便可将选中的书的status改为禁书。
第一步: 在admin.py定义如下方法,方法名你随意。
要使界面下拉框有Set to forbidden选项,可用第5句代码:
def make_forbidden(modelAdmin, request, queryset): #queryset:选中的集合;modelAdmin代表BookAdmin类,相当于self
print("----->", modelAdmin,request,queryset)
queryset.update(status="forbidden") #更改选中的为禁书
#使action框有选项set to forbidden
make_forbidden.short_description = "Set to forbidden"
第二步: 在之前定义的BookAdmin类加上actions=[xx], xx为第一步定义的方法名make_forbidden.
class BookAdmin(admin.ModelAdmin): #在类中加入下面一句代码.
actions=[make_forbidden]
admin.py
from django.contrib import admin # Register your models here.
from app01 import models def make_forbidden(modelAdmin, request, queryset): #queryset:选中的集合;modelAdmin代表BookAdmin类,相当于self
print("----->", modelAdmin,request,queryset)
queryset.update(status="forbidden") #更改选中的为禁书
#使action框有选项set to forbidden
make_forbidden.short_description = "Set to forbidden" class BookAdmin(admin.ModelAdmin): #定制book,需将类当作参数传给admin
# list_display不能显示多对多的,比如authors:
# (admin.E109) The value of 'list_display[2]' must not be a ManyToManyField.
list_display = ("id","name", "publisher","publish_date","colored_status","status") #定制为三列 search_fields = ("name", "publisher__name") #__表示出版社关联到名字
list_filter = ("publisher", "publish_date") #过滤
list_editable = ("name", "publish_date") #可修改
list_per_page = 10 #每页显示数量
#即便只有一个值也要加逗号,不然就不当成元组了
#The value of 'filter_horizontal' must be a list or tuple.
filter_horizontal = ("authors",) #选择作者时进行定制 PS:用于多对多关联
raw_id_fields = ("publisher",) #选择出版社时进行定制 PS:用于FK外键关联 actions = [make_forbidden] admin.site.register(models.Author)
admin.site.register(models.Book, BookAdmin)
admin.site.register(models.Publisher)
可别小看admin action, 比如你可以批量选中很多主机,点击action发送指令,发送文件 and so on. 强!!!
转发注明出处: http://www.cnblogs.com/0zcl/p/6580279.html
django进阶-3的更多相关文章
- Python之路,Day16 - Django 进阶
Python之路,Day16 - Django 进阶 本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...
- django进阶补充
前言: 这篇博客对上篇博客django进阶作下补充. 一.效果图 前端界面较简单(丑),有两个功能: 从数据库中取出书名 eg: 新书A 在form表单输入书名,选择出版社,选择作者(多选),输入完毕 ...
- django进阶-4
前言: 下篇博客写关于bootstrap... 一.如何在脚本测试django from django.db import models class Blog(models.Model): name ...
- Django进阶篇【1】
注:本篇是Django进阶篇章,适合人群:有Django基础,关于Django基础篇,将在下一章节中补充! 首先我们一起了解下Django整个请求生命周期: Django 请求流程,生命周期: 路由部 ...
- Django进阶知识
drf学习之Django进阶点 一.Django migrations原理 1.makemigrattions: 相当于在每个app下的migrations文件夹下生成一个py脚本文件用于创建表或则修 ...
- django进阶-查询(适合GET4以上人群阅读)
前言: 下篇博客写关于bootstrap... 一.如何在脚本测试django from django.db import models class Blog(models.Model): name ...
- django进阶-modelform&admin action
先看效果图: 登陆admin后的界面: 查看作者: 当然你也可以定制admin, 使界面更牛逼 数据库表结构: app01/models.py from django.db import models ...
- django进阶-小实例
前言: 这篇博客对上篇博客django进阶作下补充. 一.效果图 前端界面较简单(丑),有两个功能: 从数据库中取出书名 eg: 新书A 在form表单输入书名,选择出版社,选择作者(多选),输入完毕 ...
- django进阶-1
前言: 各位久等了,django进阶篇来了. 一.get与post 接口规范: url不能写动词,只能写名词 django默认只支持两种方式: get, post get是获取数据 ?user=zcl ...
随机推荐
- HDU 3782 xxx定律
xxx定律 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- ArcGIS制图技巧系列(2)地形渲染
ArcGIS制图技巧系列(2)地形渲染 by 李远祥 DEM数据是常见的地形数据,在GIS常规的制图中,DEM一直扮演着增强效果.由于带有高程值,DEM在很多情况下都在三维中显示,但这里主要介绍的是在 ...
- redis集群原理
redis是单线程,但是一般的作为缓存使用的话,redis足够了,因为它的读写速度太快了. 官方的一个简单测试: 测试完成了50个并发执行100000个请求. 设置和获取的值是一个256字节字符串 ...
- Apache常见功能实战详解
Apache 是一款使用量排名第一的 web 服务器,LAMP 中的 A 指的就是它.由于其开源.稳定.安全等特性而被广泛使用.前边的一篇文章中已经记录过如何搭建 LAMP 架构,搭建仅是第一步,其中 ...
- Spring MVC 的环境搭建和入门小程序
1.1.下载spring框架包. 1.1.1百度搜索Spring Framework. 进入spring官网,在网页右边选择想要下载的版本.如图 1.1.2进入页面按Ctrl+F搜索Distribut ...
- 浅谈C#集合【转】
集合是.NET FCL(Framework Class Library)中很重要的一部分,也是我们开发当中最常用到的功能之一,几乎是无处不在.俗话说知其然,知其所以然,平常看到IEnumerable, ...
- 在javascript中关于变量与函数的提升
在javascript中关于变量与函数的提升 一.简介 在javascript中声明变量与函数的执行步骤: 1.先预解析变量或函数声明代码,会把用var声明的变量或者函数声明的代码块进行提升操作 2. ...
- 继续学习ant
今天由于打电话,打了两个小时的电话,结果一下子错过了学习的时间段,表示很惭愧,不过查了一些资料,感觉还不错,明天继续学习吧! ant入门到精通Ant 的最完整build.xml解释ant实用实例Ant ...
- libviso中的姿态解算【转载】
这篇关于libviso的文章,本人已投稿在泡泡机器人微信公众号中,放到这里,作学习笔记用. libviso一直以来被称为在视觉里程计(VO)中的老牌开源算法.它通过corner,chessboard两 ...
- 来自高维的对抗 - 逆向TinyTool自制
一.序 无论是逆向分析还是漏洞利用,我所理解的攻防博弈无非是二者在既定的某一阶段,以高维的方式进行对抗,并不断地升级维度.比如,逆向工程人员一般会选择在Root的环境下对App进行调试分析,其是以ro ...