#一 hello django
-
创建虚拟环境**(virtualenv 和virtualenvwrapper)
1.1, virtualenv的概述
virtualenv是用来创建Python的虚拟环境的库,虚拟环境能够独立于真实环境存在,并且可以同时有多个互相独立的Python虚拟环境,每个虚拟环境都可以营造一个干净的开发环境,对于项目的依赖、版本的控制有着非常重要的作用。 虚拟环境有什么意义? 如果我们要同时开发多个应用程序,应用A需要Django1.11,而应用B需要Django1.8怎么办? 这种情况下,每个应用可能需要各自拥有一套“独立”的Python运行环境。 virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。
1.2, virtualenv 的安装和使用
1.2.1,安装和创建virtualenv
a,安装虚拟环境:安装virtualenv跟安装一般的Python库是一样的操作,直接使用pip命令就行了:
pip3 install virtualenv
b,创建虚拟环境:安装完成之后就可以使用virtualenv的命令来创建虚拟环境了,
首先需要进入需要创建虚拟环境的文件夹,比如F盘的envs文件夹,
然后使用以下命令创建一个虚拟环境,python版本的路径是可选的:
virtualenv 虚拟环境名称 [-p python版本的路径] virtualenv env1 --python==python3
如:virtualenv env1
1.2.2,启动虚拟环境:
source env1/bin/activate
进入虚拟环境后:
使用pip安装numpy模块
创建test.py文件,并在文件中使用numpy模块
在cmd命令窗口使用python test.py执行文件
1.2.3,退出虚拟环境(进入真实系统环境):
deactivate
(如果报错则使用:env1\Scripts\deactivate)
退出虚拟环境后再执行test.py:
在cmd命令窗口使用python test.py执行文件
1.3, virtualenvwrapper 的安装和使用(virtualenvwrapper是virtualenv的包装版,以后用这个,更加方便)
Windows: pip install virtualenvwrapper-win
(Linux:pip install virtualenvwrapper)
创建:mkvirtualenv 虚拟环境名称 -p python的路径
删除:rmvirtualenv 虚拟环境名称
(注意:创建的虚拟环境放在用户目录下的Envs中)
进入:workon 虚拟环境名称
退出:deactivate
ubuntu 安装虚拟环境:
1、安装 virtualenvwrapper
pip install virtualenvwrapper
2、创建目录存放虚拟环境
mkdir ~/.virtualenvs
3、在.bashrc中末尾添加
export WORKON_HOME=~/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
4、运行 source ~/.bashrc
1.4, pip常用命令
pip install xxx:安装xxx依赖包
pip list:查看所有依赖包
pip freeze:查看新安装的包
pip uninstall xxx :卸载xxx包
课堂练习:分别为python2.7和python3.6创建虚拟环境 。
-
安装django
安装Django: pip install django(也可指定某一版本 pip install django==1.11)
测试Django是否安装成功
进入python环境
import django
django.get_version()
课堂练习:在上一步创建的虚拟环境中分别安装django。 -
创建一个Django项目
进入到指定要存放项目的目录,执行 django-admin startproject xxx 来创建一个名字为xxx的工程
查看默认目录结构
manage.py:是Django用于管理本项目的命令行工具,之后进行站点运行,数据库自动生成等都是通过本文件完成。 HelloDjango/__init__.py告诉python该目录是一个python包,暂无内容,后期一些工具的初始化可能会用到 HelloDjango/settings.py Django项目的配置文件,默认状态其中定义了本项目引用的组件,项目名,数据库,静态资源等。 HelloDjango/urls.py 维护项目的URL路由映射,即定义当客户端访问时由哪个模块进行响应。 HelloDjango/wsgi.py 定义WSGI的接口信息,主要用于服务器集成,通常本文件生成后无需改动。
-
测试服务器的启动
python manage.py runserver [ip:port]
可以直接进行服务运行 默认执行起来的端口是8000 也可以自己指定ip和端口: 监听机器所有可用 ip (电脑可能有多个内网ip或多个外网ip):python manage.py runserver 0.0.0.0:8000 如果是外网或者局域网电脑上可以用其它电脑查看开发服务器,访问对应的 ip加端口,比如 10.36.132.2:8000 浏览器访问:http://localhost:8000 可以看到服务器启动成功
-
数据迁移
迁移的概念:就是将模型映射到数据库的过程生成迁移:python manage.py makemigrations
执行迁移:python manage.py migrate
-
创建应用
python manage.py startapp XXX
创建名称为XXX的应用
使用应用前需要将应用配置到项目中,在settings.py中将应用加入到INSTALLED_APPS选项中应用目录介绍
__init__.py:其中暂无内容,使得app成为一个包 admin.py:管理站点模型的声明文件,默认为空 apps.py:应用信息定义文件,在其中生成了AppConfig,该类用于定义应用名等数据 models.py:添加模型层数据类文件 views.py:定义URL相应函数(路由规则) migrations包:自动生成,生成迁移文件的 tests.py:测试代码文件
-
基本视图
首先我们在views.py中建立一个路由响应函数
from django.http import HttpResponsedef welcome(request):
return HttpResponse(‘HelloDjango’)接着我们在urls中进行注册
from App import views
url(r’^welcome/’,views.welcome)基于模块化的设计,我们通常会在每个app中定义自己的urls
在项目的urls中将app的urls包含进来
from django.conf.urls import include
url(r’^welcome/’,include(‘App.urls’))课堂练习:新建一个应用showtime,每次刷新页面显示不同的时间。
-
基本模板
模板实际上就是我们用HTML写好的页面创建模板文件夹templates, 在模板文件夹中创建模板文件
在views中去加载渲染模板, 使用render函数: return render(request,‘xxx’)
课堂练习:在上一个课堂练习中,使用template显示页面内容。
-
定义模型
在models.py 中引入models
from django.db import models创建自己的模型类,但切记要继承自 models.Model
案例驱动,使用模型定义班级,并在模板上显示班级列表
班级: table : grades columns: 班级名称 - name 成立时间 - date 女生个数 - girlnum 男生个数 - boynum 是否删除 - is_delete
-
Admin 后台管理
在admin.py中将model加入后台管理:
admin.site.register(Grade)
创建超级用户:python manage.py createsuperuser
访问admin后台:http://127.0.0.1:8000/admin/
-
展示班级列表
在views.py文件中编写班级的视图函数:
def grade_list(request):
g_list = Grade.objects.all() # 获取班级所有数据
return render(request, 'grade/grade_list.html', {
'g_list': g_list})
模板文件:
{
% for grade in g_list %}
{
{
grade.sname }}
{
% endfor %}
-
配置url
在grade App中新建urls.py文件,输入如下代码:
from django.conf.urls import url
from .views import grade_list
urlpatterns = [
url(r'^grade/$', grade_list),
]
在工程的urls.py文件中添加如下代码:
url(r'^', include('grade.urls')),
练习:
1, 从创建虚拟环境到显示出所有班级再操作至少2次
2,在班级Grade所在项目中创建学生students应用,在模板显示学生列表
学生table:students
columns:
学生姓名 - name
学生性别 - gender
学生年龄 - age
学生简介 - info
是否删除 - is_delete
定义学生类
class Students(models.Model):
name = models.CharField(max_length=20)
gender = models.BooleanField(default=True)
age = models.IntegerField()
info = models.CharField(max_length=20)
is_delete = models.BooleanField(default=False)
#二 url和模板
1. URL
URL地址说明:
[外链图片转存失败(img-56KCl1gL-1566470399509)(G:/web%E6%A1%86%E6%9E%B6/Django/day02/doc/url.png)]
使用url给视图函数传参数
在url配置中将正则部分小括号括起来。比如:
url(r'^time/plus/(\d{1,2})/$', views.hours_ahead)
如果有多个参数则用/隔开,参数需要用分组,比如:
url(r'^time/plus/(\d{1,2})/(\d{1,2})/$', views.hours_ahead),
给参数命名,使用正则分组的别名,比如:
url(r'^time/plus/(?P<time1>\d{1,2})/(?P<time2>\d{1,2})/$', views.hours_ahead)
使用分组别名之后,视图函数的参数必须用分组的别名,但是位置可以不固定。
给url取别名,那么在使用此url的地方可以使用别名。比如:
url(r'^buy/$', views.buy, name='buy'),
url(r'^login/$', views.login, name='login'),
2. 反向解析
在视图函数中,反向解析url:
from django.shortcuts import render, redirect
from django.urls import reverse
def buy(request):
return redirect(reverse('index'))
return redirect(reverse('detail', args=[2]))
return redirect(reverse('detail', kwargs={
"id": 2}))
在templates中,使用别名:
{
% url 'detail' stu.id %}
使用命名空间:
在工程的urls.py文件中,在include时,可以指定命名空间,更加细化的划分url。比如:
url(r'^App/', include('App.urls', namespace='App')),
指定命令空间后,使用反向解析时需要加上命名空间,比如:
在视图函数中: return redirect(reverse('students:index'))
在templates中: {
% url 'students:detail' %}
3. 模板
在Django框架中,模板是可以帮助开发者快速生成呈现给用户页面的工具
模板的设计方式实现了我们MVT中VT的解耦,VT有着N:M的关系,一个V可以调用任意T,一个T可以供任意V使用
模板处理分为两个过程
加载
渲染
模板主要有两个部分
HTML静态代码
动态插入的代码段(挖坑,填坑)
模板中的动态代码段除了做基本的静态填充,还可以实现一些基本的运算,转换和逻辑
模板中的变量: 视图传递给模板的数据,遵守标识符规则
语法: {
{
var }}
如果变量不存在,则插入空字符串
python manage.py shell: 进入Python环境, 且会自动导入Django配置,建议使用
>>> python manage.py shell # 进入python环境
>>> from django import template
>>> t = template.Template('My name is {
{ name }}.')
>>> c = template.Context({
'name': 'Nige'})
>>> print (t.render(c))
My name is Nige.
>>> c = template.Context({
'name': 'Barry'})
>>> print (t.render(c))
My name is Barry.
模板中的点语法
字典查询
>>> from django.template import Template, Context
>>> person = {
'name': 'Sally', 'age': '43'}
>>> t = Template('{
{ person.name }} is {
{ person.age }} years old.')
>>> c = Context({
'person': person})
>>> t.render(c)
'Sally is 43 years old.'
属性或者方法
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(2017, 5, 2)
>>> d.year
2017
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {
{ date.month }} and the year is {
{ date.year }}.')
>>> c = Context({
'date': d})
>>> t.render(c)
'The month is 5 and the year is 2017.'
>>> from django.template import Template, Context
>>> class Person(object):
... def __init__(self, first_name, last_name):
... self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {
{ person.first_name }} {
{ person.last_name }}.')
>>> c = Context({
'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'
方法不能有参数。
>>> from django.template import Template, Context
>>> t = Template('{
{ var }} -- {
{ var.upper }} -- {
{ var.isdigit }}')
>>> t.render(Context({
'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({
'var': '123'}))
'123 -- 123 -- True'
列表,使用索引,不允许负索引
>>> from django.template import Template, Context
>>> t = Template('Item 2 is {
{ items.2 }}.')
>>> c = Context({
'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'
模板中的小弊端,调用对象的方法,不能传递参数
模板中的标签
语法 {
% tag %}
作用
1. 加载外部传入的变量
2. 在输出中创建文本
3. 控制循环或逻辑
if 语句:
格式:
if单分支
{
% if 表达式 %}
语句
{
% endif %}
if双分支
{
% if 表达式 %}
语句
{
% else %}
语句
{
% endif %}
if多分支
{
% if 表达式 %}
语句
{
% elif 表达式 %}
语句
{
% else %}
语句
{
% endif %}
判断true或false
{
% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{
% endif %}
使用and or not,可结合使用,and具有更高优先权。
{
% if athlete_list and coach_list %}
<p>Both athletes and coaches are available.</p>
{
% endif %}
{
% if not athlete_list %}
<p>There are no athletes.</p>
{
% endif %}
{
% if athlete_list or coach_list %}
<p>There are some athletes or some coaches.</p>
{
% endif %}
{
% if not athlete_list or coach_list %}
<p>There are no athletes or there are some coaches.</p>
{
% endif %}
{
% if athlete_list and not coach_list %}
<p>There are some athletes and absolutely no coaches.</p>
{
% endif %}
使用多个相同的逻辑操作关键字也是允许的,比如:
{
% if athlete_list or coach_list or parent_list or teacher_list %}
使用in和not in,
{
% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{
% endif %}
{
% if user not in users %}
If users is a list, this will appear if user isn't an element of the list.
{
% endif %}
使用is 和is not
{
% if somevar is True %}
This appears if and only if somevar is True.
{
% endif %}
{
% if somevar is not None %}
This appears if somevar isn't None.
{
% endif %}
for 语句:
{
% for 变量 in 列表 %}
语句1
{
% empty %}
语句2
{
% endfor %}
当列表为空或不存在时,执行empty之后的语句
{
{
forloop.counter }} 表示当前是第几次循环,从1数数
{
% for item in todo_list %}
<p>{
{
forloop.counter }}: {
{
item }}</p>
{
%endfor %}
{
{
forloop.counter0}}表示当前是第几次循环,从0数数
{
{
forloop.revcounter}}表示当前是第几次循环,倒着数数,到1停
{
{
forloop.revcounter0}}表示当前第几次循环,倒着数,到0停
{
{
forloop.first }} 是否是第一个 布尔值
{
% for object in objects %}
{
% if forloop.first %}
<li class="first">
{
% else %}
<li>
{
% endif %}
{
{
object }}</li>
{
% endfor %}
{
{
forloop.last }} 是否是最后一个 布尔值
{
% for link in links %}
{
{
link }}{
% if not forloop.last %} | {
% endif %}
{
% endfor %}
forloop.parentloop
{
% for country in countries %}
<table>
{
% for city in country.city_list %}
<tr>
<td>Country #{
{ forloop.parentloop.counter }}</td>
<td>City #{
{ forloop.counter }}</td>
<td>{
{
city }}</td>
</tr>
{
% endfor %}
</table>
{
% endfor %}
注释:
单行注释
{
# 被注释掉的内容 #}
多行注释
{
% comment %}
内容
{
% endcomment %}
过滤器:
{
{
var|过滤器 }}
作用:在变量显示前修改
add {
{
value|add:2 }}
没有减法过滤器,但是加法里可以加负数
{
{
value|add:-2 }}
lower
{
{
name|lower }}
upper
{
{
my_list|first|upper }}
截断:
{
{
bio|truncatechars:30 }}
过滤器可以传递参数,参数需要使用引号引起来
比如join: {
{
students|join:'=' }}
默认值:default,格式 {
{
var|default:value}}
如果变量没有被提供或者为False,空,会使用默认值
根据指定格式转换日期为字符串,处理时间的
就是针对date进行的转换
{
{
dateVal | date:'y-m-d' }}
HTML转义
将接收到的数据当成普通字符串处理还是当成HTML代码来渲染的一个问题
渲染成html:{
{
code|safe }}
关闭自动转义
{
% autoescape off%}
code
{
% endautoescape %}
打开自动转义转义
{
% autoescape on%}
code
{
% endautoescape %}
模板继承
block:挖坑
{
% block XXX%}
code
{
% endblock %}
extends 继承,写在开头位置
{
% extends '父模板路径' %}
include: 加载模板进行渲染
{
% include '模板文件' %}
Django中默认集成了后台数据管理页面,通过简单的配置就可以实现模型后台的Web控制台。
管理界面通常是给系统管理员使用的,用来完成数据的输入,删除,查询等工作。
使用以下models来示范admin后台系统的用法。
创建一个项目。用来说明出版社,书籍和作者的关系。
1. 出版社,书籍,作者都有一个首页index.html
2. 在书籍的index.html中有一个"查看所有书籍"的超链接按钮,可以点击进入书籍列表list.html页面
3. 在书籍list.html中显示所有书名,点击书名可以进入书籍详情detail.html
4,在书籍detail.html中可以点击该书的作者和出版社,进入作者的detail.html和出版社的detail.html页面
假定关系:书籍:作者 => n:n (一本书可以由多个作者共同完成, 一个作者也可以创作多本书)
出版社:书籍 => 1:n (一个出版社可以出版多本书, 一本书由一个出版社出版)
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(null=True, blank=True)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
使用admin后台系统之前,需要先创建一个系统管理员,创建管理员之前需先同步数据库。
python manager.py createsuperuser
设置为中文
settings中LANGUAGE_CODE = 'zh-hans'
设置时间,时区
TIME_ZONE='Asia/Shanghai'
添加自己的数据模型
在admin.py中注册
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book))
在admin中给model添加数据。
给模型加上__str__函数,比如给Author模型添加str函数,让author的显示更加友好:
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
希望控制admin中添加model数据时的动作,可以修改相应字段的属性。
比如author的email字段运行添加的时候为空,可以在email字段定义中加上 blank=True(可以空白),
比如book的publication_date添加 blank=True, null=True(可以为null)属性。
修改models属性之后记得及时做数据迁移。
使用verbose_name属性指定字段的别名:
比如给publisher的name字段指定一个中文的别名verbose_name='出版社名称'。
在models的修改页面,默认显示的是models定义的str函数返回的字符串。
通过定义MoldelAdmin来定制model在admin的表现。比如给Author定义AuthorAdmin。
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
相应的注册代码也要变化:
admin.site.register(Author, AuthorAdmin)
给Author添加一个搜索框:
search_fields = ('first_name', 'last_name')
给book添加一个过滤器
list_filter = ('publication_date',)
过滤器不光可以作用在日期字段上,还可以作用在boolean类型和外键上。
另一种增加日期过滤的方式:
date_hierarchy