https://www.cnblogs.com/0zcl/archive/2017/03/22/6580279.html

先看效果图:

登陆admin后的界面:

查看作者:

当然你也可以定制admin, 使界面更牛逼

数据库表结构: app01/models.py

 1 from django.db import models
2 from django.utils.html import format_html #把字符串变成html
3
4 # Create your models here.
5 class Author(models.Model):
6 first_name = models.CharField(max_length=32)
7 last_name = models.CharField(max_length=32)
8 email = models.EmailField()
9
10 def __str__(self):
11 return "<%s %s>" % (self.first_name,self.last_name)
12
13 class Meta:
14 verbose_name_plural = u"作者"
15
16 class Publisher(models.Model):
17 name = models.CharField(max_length=64, unique=True)
18 address = models.CharField(max_length=128,null=True,blank=True)
19 city = models.CharField(max_length=64)
20 state_province = models.CharField(max_length=64,help_text="put your province here",verbose_name=u"所属省")
21 country = models.CharField(max_length=64,editable=False)
22 website = models.URLField()
23
24 def __str__(self):
25 return "<%s>" % (self.name)
26
27 class Book(models.Model):
28 name = models.CharField(max_length=128)
29 authors = models.ManyToManyField(Author) #书多对多到作者
30 publisher = models.ForeignKey(Publisher) #一对多
31 publish_date = models.DateField() #精确到天DateField()
32 status_choices = (("published", u"已出版"),
33 ("producing", u"待出版"),
34 ("forbidden", u"禁书"),
35 )
36 # 此时应该给个默认值,给之前没有status字段的书。
37 status = models.CharField(choices=status_choices, max_length=32, default="producing")
38
39 def __str__(self):
40 return "<%s %s>" % (self.name,self.publisher)
41
42
43 def colored_status(self):
44 if self.status == "published":
45 format_td = format_html("<span style='padding:2px;已出版</span>")
46 elif self.status == "producing":
47 format_td = format_html("<span style='padding:2px;待出版</span>")
48 elif self.status == "forbidden":
49 format_td = format_html("<span style='padding:2px;禁书</span>")
50
51 return format_td
52
53 colored_status.short_description = "STATUS" #页面显示为colored_status即方法名,这里改名为STATUS

现在你看到我直接贴代码,肯定不爽。好吧……

首先上面有三张表: Author(作者表)、Publisher(出版社表)、Book(图书表)。表与表的关联也很简单,一本书可由多个作者联合出,一个作者可出多本书,书与作者为ManyToMany关系;一本书只能由一个出版社出版,一个出版社可出多本书,一对多,用外键ForeignKey关联。

其它的__str__是啥?verbose_name是毛线东西? 看我之前的博客咯。

你登陆admin后其实是看不到3张表的,需要在admin.py注册一下:

1 from app01 import models
2
3 admin.site.register(models.Author)
4 admin.site.register(models.Book, BookAdmin)
5 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类(也可以命名为别的~)

1 from django import forms
2 from app01 import models
3
4 class BookForm(forms.Form):
5 name = forms.CharField(max_length=10)
6 # publisher_id = forms.IntegerField(widget=forms.Select)
7 publish_date = forms.DateField()

第二步: 处理用户请求

用户最开始请求数据是GET方式, 当输入数据后修改数据(创建图书),提交方式为POST

 1 def book_form(request):
2 form = forms.BookForm() # 生成form实例
3 if request.method == "POST":
4 print(request.POST)
5 form = forms.BookForm(request.POST)
6 if form.is_valid(): #进行验证
7 print("form is ok")
8 print(form)
9 print(form.cleaned_data) #{'name': 'qq', 'publish_date': datetime.date(2017, 3, 14)}
10 form_data = form.cleaned_data
11 form_data["publisher_id"] = request.POST.get("publisher_id")
12 book_obj = models.Book(**form_data) #form_data为字典形式
13 book_obj.save()
14 else:
15 print(form.errors)
16 publisher_list = models.Publisher.objects.all()
17
18
19 return render(request, "app01/book_form.html", {"book_form":form,
20 "publishers":publisher_list})

当用户发起GET请求时,要生成一个空的form实例,并从数据库中查找所有的出版社publisher_list,之后进行渲染render. 接下来当然得写book_form.html啦。

 1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 </head>
7 <body>
8 <form action="" method="POST">{% csrf_token %}
9 {{ book_form }}
10 <select name="publisher_id">
11 {% for publisher in publishers %}
12 <option value="{{ publisher.id }}">{{ publisher.name }}</option>
13 {% endfor %}
14 </select>
15 <input type="submit" value="创建图书"/>
16 </form>
17 </body>
18 </html>

要是上面看不懂了,就别往下看了……可以看下我之前的博客哈。根据上面的html,会出现如下界面:

当你输入书名等信息,再点创建图书时,此时是以POST方式发起请求。

我们要将数据发给django强大的form表单进行验证(你可能没有输入或者日期输入为SB), 这些属于前端的验证,前端的验证是为了减轻后台服务器的压力。只需将请求的数据request.POST传给forms.py的BookForm()即可。

1
form = forms.BookForm(request.POST)

此时我们还需要进行后台验证,有可能成功,also可能失败。当验证成功时,form.is_valid返回true.

1
if form.is_valid():   #进行验证

验证成功后,自然是获取数据,存到数据库创建图书啦。好,信息是封装在form实例的,现打印form:

 

擦,一堆html

要获取干净的数据,需处理一下:

1
form_data = form.cleaned_data
 

form表单定制ending.

这里有个问题,为啥要在BookForm去掉publisher_id字段??

因为无法直接获取出版社的信息(下拉列表为空的),要想在前端界面有供选择出版社的input标签,需要自己在html添加

 

最后还需要将获得的信息加到字典(干净的数据)中,再添加到数据库。
呵呵,这比较麻烦,下面介绍更优化的方法。

modelform

为了解决前面无法获取publisher_id的问题,引入modelform

modelform与form有很多相似之处的。接下来用modelform做个前端表单,当然,会丑点……

第一步:

在forms.py创建类,继承forms.ModelForm:

可绑定Book表,Book表有什么字段,form表单就有什么字段,当然你也可以用fields使想显示的字段显示在界面。

 1 class BookModelForm(forms.ModelForm):
2
3 class Meta:
4 model = models.Book #绑定Book类
5 #fields = {"name", "publish_date"} #只包括name,publish-date字段
6 exclude = () #代表所有字段都包括
7 widgets = {
8 # 可以定义css样式,牛逼啊
9 "name": forms.TextInput(attrs={"class":"form-control"}),
10 }

第二步: 处理用户请求

 1 def book_modelform(request):
2 form = forms.BookModelForm
3 print(request.POST)
4 if request.method == "POST":
5 form = forms.BookModelForm(request.POST)
6 if form.is_valid(): # 进行验证
7 print("form is ok")
8 print(form)
9 print(form.cleaned_data) # {'name': 'qq', 'publish_date': datetime.date(2017, 3, 14)}
10 form.save()
11
12 return render(request, "app01/book_modelform.html", {"book_form":form})

第三步: 写html模版,book_modelform.html:

 1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 <style>
7 .form-control{
8 color: red;
9 }
10 </style>
11 </head>
12 <body>
13 <form action="" method="post">{% csrf_token %}
14 {{ book_form }}
15 <input type="submit" value="创建新书"/>
16 </form>
17
18 </body>
19 </html>

效果图:

app01/forms.py

 

二、admin定制

费话不多说,先上效果图:

第一次看到这界面效果,卧槽,amazing....

django的admin后台可以定制成上面的形式,当然你也可以自己定制得更漂亮。

在admin.py加上一个继承admin.ModelAdmin的类

 1 class BookAdmin(admin.ModelAdmin):  #定制book,需将类当作参数传给admin
2 # list_display不能显示多对多的,比如authors:
3 # (admin.E109) The value of 'list_display[2]' must not be a ManyToManyField.
4 list_display = ("id","name", "publisher","publish_date","colored_status","status") #定制为三列
5
6 search_fields = ("name", "publisher__name") #__表示出版社关联到名字
7 list_filter = ("publisher", "publish_date") #过滤
8 list_editable = ("name", "publish_date") #可修改
9 list_per_page = 10 #每页显示数量
10 #即便只有一个值也要加逗号,不然就不当成元组了
11 #The value of 'filter_horizontal' must be a list or tuple.
12 filter_horizontal = ("authors",) #选择作者时进行定制 PS:用于多对多关联
13 raw_id_fields = ("publisher",) #选择出版社时进行定制 PS:用于FK外键关联
14
15 actions = [make_forbidden]

定制后完,需将类当作参数传给admin:

1
admin.site.register(models.Book, BookAdmin)

定制作者与出版社的效果图:

ok, 现在有个新需求,想在book界面有个可以选择书出版或未出版的功能,如何实现呢? 而且可以给界面的已出版/未出版加上颜色样式??

首先你要给book表加上一个新的字段:

1     status_choices = (("published", u"已出版"),
2 ("producing", u"待出版"),
3 ("forbidden", u"禁书"),
4 )
5 # 此时应该给个默认值,给之前没有status字段的书。
6 status = models.CharField(choices=status_choices, max_length=32, default="producing")
7
8 def __str__(self):
9 return "<%s %s>" % (self.name,self.publisher)

再将status字段加到list_display,就能显示在界面上了。so easy.

如何实现上图的颜色呢??

在models.py下的Book类(用于创建Book表),定义colored_status方法(也可定义为别的名~) 加入下面代码:

 1     def colored_status(self):
2 if self.status == "published":
3 format_td = format_html("<span style='padding:2px;已出版</span>")
4 elif self.status == "producing":
5 format_td = format_html("<span style='padding:2px;待出版</span>")
6 elif self.status == "forbidden":
7 format_td = format_html("<span style='padding:2px;禁书</span>")
8
9 return format_td
10
11 colored_status.short_description = "STATUS" #页面默认显示为colored_status即方法名,这里改名为STATUS

自我感觉注释得挺明白的。对不同的status判断,并返回不同的css样式。

这里注意导入format_html,可将字符串变成对应html

1
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句代码:

1 def make_forbidden(modelAdmin, request, queryset):  #queryset:选中的集合;modelAdmin代表BookAdmin类,相当于self
2 print("----->", modelAdmin,request,queryset)
3 queryset.update(status="forbidden") #更改选中的为禁书
4 #使action框有选项set to forbidden
5 make_forbidden.short_description = "Set to forbidden"

第二步: 在之前定义的BookAdmin类加上actions=[xx], xx为第一步定义的方法名make_forbidden.

1
2
class BookAdmin(admin.ModelAdmin):   #在类中加入下面一句代码.
    actions=[make_forbidden]

admin.py

 

可别小看admin action, 比如你可以批量选中很多主机,点击action发送指令,发送文件  and so on. 强!!!

自定义django model form、admin action的更多相关文章

  1. Django Model Form

    ModelForm ModelForm结合了Form和Model,将models的field类型映射成forms的field类型,复用了Model和Model验证, 写更少的代码,并且还实现了存储数据 ...

  2. django model form 保存方法 django-rest-framework save 修改某一项值 方法

    django Model Form django-rest-framework save 方法 修改某个数据的值

  3. django进阶-modelform&admin action

    先看效果图: 登陆admin后的界面: 查看作者: 当然你也可以定制admin, 使界面更牛逼 数据库表结构: app01/models.py from django.db import models ...

  4. 自定义django的admin后台action

    django的admin后台管理系统中自带了一个批量删除所选对象的action. 我们还可以添加自定义的action来实现其它类似的功能,如批量修改某个字段的功能.简单的,例如将文章批量标记为已发布的 ...

  5. Day19 Django之Form表单验证、CSRF、Cookie、Session和Model操作

    一.Form表单验证 用于做用户提交数据的验证1.自定义规则 a.自定义规则(类,字段名==html中的name值)b.数据提交-规则进行匹配代码如下: """day19 ...

  6. 自定义 Django的User Model,扩展 AbstractUser类注意事项

    本篇主要讨论一下User Model的使用技巧. 注意, 由于Django 1.5之后user model带来了很大的变化, 本篇内容只针对django 1.5之后的版本. 1. 确定 User Mo ...

  7. 自定义django admin及其界面

    1.在项目目录下新创建一个app,命名为kingadmin,在templates目录下新建kingadmin目录,用来存放相关页面的模板文件,新建一个templatetags目录,用来存放处理前端模板 ...

  8. Django 的 model form 组件

    Django 的 model form 组件 Model Form 组件的由来 之前介绍过 Django 的 Form 组件(Django的Form表单)使用方法,Form 组件能够帮我们做三件事: ...

  9. 14 Django之Form和Model Form组件

    一.什么是Form 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用 ...

随机推荐

  1. svn出错:directory 'xxxx' is out of date

  2. 指针和const一些注意事项

    1.常量指针(底层const) 指向常量的指针,指针所指向的对象的值无法被修改,若想存放常量对象的地址,只能使用指向常量的指针. 2.指针常量(顶层const) 指针本身是常量,指针本身的值不可修改. ...

  3. 配置total commander 显示所有或特定文件夹 (带点的文件夹)

    在配置|忽略列表 下可以添加或删除需要隐藏的文件夹通配符.

  4. MyEclipse 2017 Stable 2.0发布|附下载

    MyEclipse个人开发者专享6.9折!仅剩最后3天!在线订购>> 2017 Stable 2.0版本带来了新的功能和修复,从Stable 1.0以来,已经发布了几个版本的Angular ...

  5. ios平台cocos2d-x播放音频、视频、音效的Demo(支持网络视频)

    最近由ios应用转做游戏,游戏开始时需要播放一个视频,由于本身cocos2d-x播放视频的相关库,在网上搜到的资料都不是很全,我自己试过在cocos2dx直接调用ios的MediaPlayer来播放, ...

  6. wilber3申请数据的直接目录寻找

    ftp://ds.iris.edu/pub/userdata/

  7. secureCRT 字体颜色、文件夹和文件显示的颜色

    secureCRT菜单栏中选择会话选项 修改显示文件夹和文件显示的颜色 修改字体样式 查看效果

  8. Maven私服Nexus详解

    maven的仓库只有两大类:1.本地仓库 2.远程仓库,在远程仓库中又分成了3种:2.1 中央仓库 2.2 私服 2.3 其它公共库. 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理 ...

  9. OC基础:类和对象 分类: ios学习 OC 2015-06-12 18:55 17人阅读 评论(0) 收藏

    OC:Objective-c     面向对象的c语言,简称obj-c或者OC OC和C的区别 1.OC是C语言的超集,OC是在C语言的基础上结合smalltalk的优点,开发出来的语言.oc兼容所有 ...

  10. 简单shell实现局域网IP扫描

    #!/bin/bash network=$1 time=$(date +%H%M%S) for i in $(seq $2 $3) do ping -c 1 -w 2 $network.$i > ...