我的python之路【第十四章】Django站点管理(Admin)
1.3 管理站点:
1.3.1 启动服务器
-
运行如下命令可以开启服务器
python manage.py runserver ip:port
-
可以不写ip,默认端口为8000
-
这是一个纯python编写的轻量级web服务器,仅在开发阶段使用
-
服务器成功启动后,提示如下信息:
(MyTest) [root@docker-1 test1]# python manage.py runserver Performing system checks... System check identified no issues (0 silenced). May 16, 2018 - 07:55:07 Django version 1.8.2, using settings 'test1.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
-
默认端口是8000,可以修改端口
python manage.py runserver 8080
-
打开浏览器,输入网址“127.0.0.1:8000”可以打开默认页面
-
如果修改文件不需要重启服务器,如果增删文件需要重启服务器
-
通过ctrl+c停止服务器
1.3.2 管理操作(admin)
- 站点分为“内容发布”和“公共访问”两部分
- “内容发布”的部分负责添加、修改、删除内容,开发这些重复的功能是一件单调乏味、缺乏创造力的工作。为此,Django会根据定义的模型类完全自动地生成管理模块
1) 使用django的管理
-
创建一个管理员用户
python manage.py createsuperuser,按提示输入用户名、邮箱、密码
-
启动服务器,通过“127.0.0.1:8000/admin”访问,输入上面创建的用户名、密码完成登录
-
进入管理站点,默认可以对groups、users进行管理
2) 管理界面本地化
-
编辑settings.py文件,设置编码、时区
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
5) 向admin注册booktest的模型
from django.contrib import admin
from models import BookInfo
admin.site.register(BookInfo)
- 刷新管理页面,可以对BookInfo的数据进行增删改查操作
- 问题:如果在str方法中返回中文,在修改和添加时会报ascii的错误
- 解决:在str()方法中,将字符串末尾添加“.encode('utf-8')”
6) 自定义管理页面
-
Django提供了admin.ModelAdmin类
-
通过定义ModelAdmin的子类,来定义模型在Admin界面的显示方式
class QuestionAdmin(admin.ModelAdmin): ... admin.site.register(Question, QuestionAdmin)
列表页属性
-
list_display:显示字段,可以点击列头进行排序
list_display = ['pk', 'btitle', 'bpub_date']
-
list_filter:过滤字段,过滤框会出现在右侧
list_filter = ['btitle']
-
search_fields:搜索字段,搜索框会出现在上侧
search_fields = ['btitle']
-
list_per_page:分页,分页框会出现在下侧
list_per_page = 10
添加、修改页属性
-
fields:属性的先后顺序
fields = ['bpub_date', 'btitle']
-
fieldsets:属性分组
fieldsets = [ ('basic',{'fields': ['btitle']}), ('more', {'fields': ['bpub_date']}), ]
7) 关联对象
-
对于HeroInfo模型类,有两种注册方式
- 方式一:与BookInfo模型类相同
- 方式二:关联注册
-
按照BookInfor的注册方式完成HeroInfo的注册
-
接下来实现关联注册
from django.contrib import admin from models import BookInfo,HeroInfo class HeroInfoInline(admin.StackedInline): model = HeroInfo extra = 2 class BookInfoAdmin(admin.ModelAdmin): inlines = [HeroInfoInline] admin.site.register(BookInfo, BookInfoAdmin) 备注: 会在BookInfo管理页面中出现HeroInfo的信息 model 指定表:admin.StackedInline extra 显示几条信息
-
可以将内嵌的方式改为表格(比上面分布合理)
class HeroInfoInline(admin.TabularInline)
8) 布尔值的显示
-
发布性别的显示不是一个直观的结果,可以使用方法进行封装
def gender(self): if self.hgender: return '男' else: return '女' gender.short_description = '性别'
-
在admin注册中使用gender代替hgender
class HeroInfoAdmin(admin.ModelAdmin): list_display = ['id', 'hname', 'gender', 'hcontent']
1.4 视图
-
在django中,视图对WEB请求进行回应
-
视图接收reqeust对象作为第一个参数,包含了请求的信息
-
视图就是一个Python函数,被定义在views.
#coding:utf-8 from django.http import HttpResponse def index(request): return HttpResponse("index") def detail(request,id): return HttpResponse("detail %s" % id)
-
定义完成视图后,需要配置urlconf,否则无法处理请求
1.4.1 URLconf
-
在Django中,定义URLconf包括正则表达式、视图两部分
-
Django使用正则表达式匹配请求的URL,一旦匹配成功,则调用应用的视图
-
注意:只匹配路径部分,即除去域名、参数后的字符串
-
在test1/urls.py插入booktest,使主urlconf连接到booktest.urls模块
url(r'^', include('booktest.urls')),
-
在booktest中的urls.py中添加urlconf
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.index), url(r'^([0-9]+)/$', views.detail), ]
1.5 模板
-
模板是html页面,可以根据视图中传递的数据填充值
-
创建模板的目录如下图:
├── manage.py ├── templates │ └── booktest └── test1
-
修改settings.py文件,设置TEMPLATES的DIRS值
'DIRS': [os.path.join(BASE_DIR, 'templates')],
-
在模板中访问视图传递的数据
{{输出值,可以是变量,也可以是对象.属性}} {%执行代码段%}
1.5.1 定义index.html模板
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>图书列表</h1>
<ul>
{%for book in booklist%}
<li>
<a href="{{book.id}}">
{{book.btitle}}
</a>
</li>
{%endfor%}
</ul>
</body>
</html>
1.5.2 定义detail.html模板
-
在模板中访问对象成员时,都以属性的方式访问,即方法也不能加括号
<!DOCTYPE html> <html> <head> <title>详细页</title> </head> <body> <h1>{{book.btitle}}</h1> <ul> {%for hero in book.heroinfo_set.all%} <li>{{hero.hname}}---{{hero.hcontent}}</li> {%endfor%} </ul> </body> </html>
1.5.3 使用模板
-
编辑views.py文件,在方法中调用模板 (此方法没成功-用于理解学习模板渲染过程)
from django.http import HttpResponse from django.template import RequestContext, loader from models import BookInfo def index(request): booklist = BookInfo.objects.all() template = loader.get_template('booktest/index.html') context = RequestContext(request, {'booklist': booklist}) return HttpResponse(template.render(context)) def detail(reqeust, id): book = BookInfo.objects.get(pk=id) template = loader.get_template('booktest/detail.html') context = RequestContext(reqeust, {'book': book}) return HttpResponse(template.render(context))
1.5.4 去除模板的硬编码
-
在index.html模板中,超链接是硬编码的,此时的请求地址为“127.0.0.1/1/”
<a href="{{book.id}}">
-
此时的请求地址应该为“127.0.0.1/book/1/”
-
问题总结:如果在模板中地址硬编码,将来urlconf修改后,地址将失效
-
解决:使用命名的url设置超链接
-
修改test1/urls.py文件,在include中设置namespace
url(r'^', include('booktest.urls', namespace='booktest')),
-
修改booktest/urls.py文件,设置name
url(r'^book/([0-9]+)/$', views.detail, name="detail"),
-
修改index.html模板中的链接
<a href="{%url 'booktest:detail' book.id%}">
1.5.5 Render简写 (常用写法)
-
Django提供了函数Render()简化视图调用模板、构造上下文
from django.shortcuts import render from models import BookInfo def index(reqeust): booklist = BookInfo.objects.all() return render(reqeust, 'booktest/index.html', {'booklist': booklist}) def detail(reqeust, id): book = BookInfo.objects.get(pk=id) return render(reqeust, 'booktest/detail.html', {'book': book})