Django 基础

一 概述

1 基本概述

Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。

Django是一个开放源代码的Web应用框架,由Python写成。

Django遵守BSD版权,初次发布于2005年7月, 并于2008年9月发布了第一个正式版本1.0 。

Django采用了MVC的软件设计模式,即模型M,视图V和控制器C。

所以Django的设计目标就是一款大而全,便于企业开发项目的框架,因此企业应用较为广泛

2 优点

1 能够快速开发,如Auth,Cache模板
2 MVC设计模式
3 实用的管理后台
4 自带ORM,Template,Form,Auth核心
5 组件
6 简洁的URL设计
7 周边插件丰富

3 缺点

重量级,因为东西大而全
同步阻塞

4 Django版本

Django version python version
1.8 2.7 3.2 3.3 3.4 3.5
1.9 1.10 2.7 3.4 3.5
1.11 2.7 3.4 3.5 3.6
2.0 3.4 3.5 3.6
2.1 3.5 3.6 3.7

建议不要随便尝试新版本,因为其可能会有问题

二 Django 基本安装

1 安装

1 安装虚拟环境

python3.5.4 Django 版本2.0

mkdir test  // 创建test目录
pyenv   virtualenv  3.5.4  test  //创建test虚拟账号
cd test/
pyenv local test  //设置虚拟环境 

结果如下

Django 基础

2 安装

 pip  install  django==2.0

Django 基础

3 创建Django项目

创建名称为test.dj的项目

django-admin  startproject  testdj  .

项目结构如下

Django 基础

上述命令就在当前目录中创建了Django项目的初始化文件,点表示项目的根目录

重要文件说明

manage.py:本项目管理的命令行工具,应用创建,数据库迁移,等都需要其完成,
testdj/settings.py: 本项目配置文件,数据库参数等 
testdj/urls.py:URL路径映射配置,默认情况下,只配置了/admin的路由
testdj/wsgi:定义WSGI接口信息,一般无需改动

4 pycharm 连接远端Linux服务环境

设置本地项目路径

Django 基础

连接远端项目

Django 基础

连接远端

Django 基础

远端地址

Django 基础

SSH连接

Django 基础

若端口不同可修改端口

配置密码

Django 基础

配置项目映射和相关项目环境

Django 基础

结果如下

Django 基础

数据拉取

Django 基础

5 数据库相关配置

数据库必须启动,其用户名密码必须存在

Django 基础

创建test库

Django 基础

Django连接配置

Django 基础

相关参数详解

'ENGINE' : 连接引擎
'NAME':连接数据库用户名
'PASSWORD':连接数据库密码
'HOST':数据库主机IP地址,缺省字符串,代表localhost,如果是'/'开头表示Unix socket 连接
'POST':端口


数据库引擎ENGINE

内建的引擎有

django.db.backends.postgresql
django.db.backends.mysql
django.db.backends.sqlite3
django.db.backends.oracle

django 在配置时需要加载mysql的配置,因此其是全局配置,连接数据库的配置,在启动时必须被加载,其中settings.py是最早被加载的

数据库驱动配置

驱动地址

https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-notes

Django支持MySQL 5.5+
Django的官方推荐版本是mysql 1.3.7 +


安装驱动

 pip install mysqlclient

结果如下

Django 基础

执行迁移文件,其本身的数据库配置

python  manage.py   migrate

结果如下

Django 基础

2 创建应用

1 Linux端命令行创建相关应用

python  manage.py   startapp  testapp

Django 基础

2 相关目录结构如下

Django 基础

3 相关文件详解

admin.py 管理站点模型的声明文件

models.py 模型层Model类定义

views.py 定义URL 响应函数

migrations包。数据库迁移文件生成目录

apps.py 应用的信息定义文件

4 注册应用

在 settings.py中,增加testapp应用,目的是为了后台管理admin使用。或者迁移 migrate 使用

Django 基础

3 配置管理后台

1 创建管理员
设置用户名为admin,密码为admin123

 ./manage.py  createsuperuser

结果如下

Django 基础

6 本地化,配置时区和语言设置,在testdj/settings.pt中配置

Django 基础

7 启动web Server

修改配置文件允许所有主机访问

Django 基础

启动

 python  manage.py   runserver  0.0.0.0:8000

默认启动为8000端口
如下

Django 基础

Django 基础

Django 基础

Django 基础

三 Django 模板技术

1 概述

如果使用react实现前端的页面功能,其实Django就没必要使用模板,它其实就是一个后台服务器程序,接受请求,响应数据,接口设计就可以是一个纯粹的Reasrful 风格

模板的目的就是为了可视化,将数据按照一定的布局格式输出,而不是为了数据处理,所以一般不会有复杂的逻辑,模板的引入实现了业务逻辑和显示格式的分离,这样,在开发中,就可以分工工作,页面开发完成的页面布局设计,后台开发完成数据处理逻辑的实现

python的模板引擎默认使用Django template language (DTL)构建

2 模板配置

1 设置模板路径

在settins.py中,设置模板项目的路径

Django 基础

名词解释

DIRS 列表,定义模板文件的搜索路径顺序

BACKEND 指定项目默认引擎

APP_DIRS 是否运行在每个已安装的应用中查找模板

BASE_DIR 是项目的根目录,os.path.join(BASE_DIR,'templates')就是在manage.py这层建立一个目录templates,这路径是后面找模板的地方。

2 创建模板文件

项目目录中添加相关文件夹并在其中创建index.html文件

Django 基础

3 模板渲染

模板处理2个步骤

1 加载模板
模板是一个文件,需要从磁盘中读取并加载,要将模板放置在上述指定的目录中

2 渲染

模板需要使用内容数据来渲染,生成对应的HTML文件内容

4 基本代码实现

在testdj/urls.py中配置如下

Django 基础

相关代码

from django.contrib import admin
from django.urls import path
from  django.conf.urls  import  url   # 导入url用于匹配多个后缀服务
from   django.shortcuts import   render  # 导入渲染模板
def  index(request):
    print  (request)
    print  (type(request))
    return    render(request,'index.html',{'user':'hello world'})

urlpatterns = [
    url(r'^admin/', admin.site.urls),  # 正则匹配,以admin 开头的调度到admin.site.urls中
    url(r'^index/',index),  #同上
    url(r'^$',index),
]

render 源码如下

def render(request, template_name, context=None, content_type=None, status=None, using=None):
    """
    Return a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

上述中还可以传递状态码等参数,但第一个必须是request,第二个必须是模板名称,

处理模块填充相关问题

def render_to_string(template_name, context=None, request=None, using=None):
    """
    Load a template and render it with a context. Return a string.

    template_name may be a string or a list of strings.
    """
    if isinstance(template_name, (list, tuple)):
        template = select_template(template_name, using=using)  # 解决模板找到模板名称的问题,在配置文件中寻找
    else:
        template = get_template(template_name, using=using)
    return template.render(context, request)  # 此处是使用模板来填充数据,并将其输出出来,其中包含请求和响应内容 

搜索模板相关代码

def get_template(template_name, using=None):
    """
    Load and return a template for the given name.

    Raise TemplateDoesNotExist if no such template exists.
    """
    chain = []
    engines = _engine_list(using)
    for engine in engines:
        try:
            return engine.get_template(template_name)
        except TemplateDoesNotExist as e:
            chain.append(e)

    raise TemplateDoesNotExist(template_name, chain=chain)

index 代码如下

Django 基础

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
test <h1>{{ user  }}</h1>  <!--此处必须和前面的最后一列中的名称相对应,否则将不能被识别到-->
</body>
</html>

Django 基础

Django 基础

加载方法相当于使用open将文件打开,渲染方法将其中的{{}}中的内容进行填充,填充好后交给httpresponse 的body,进行传递头部,约定编码,相关压缩情况,当正文来了后先看编码格式,后看title,最后加载body的渲染内容


下载是不渲染的,发起HTTP请求,服务器将文件打开,文件流传输,其类型是普通文件,其不会渲染成dom树,其不会做相关的操作,下载不需要dom,只有转换成DOM才能渲染,

from django.contrib import admin
from django.urls import path
from  django.http  import HttpResponse,JsonResponse
from  django.conf.urls  import  url   # 导入url用于匹配多个后缀服务
from   django.shortcuts import   render  # 导入渲染模板
def  index(request):
    print  (request)
    print  (type(request))
    return    JsonResponse({'user':'hello world'})  # 此处返回结果为一个json格式的数据

urlpatterns = [
    url(r'^admin/', admin.site.urls),  # 正则匹配,以admin 开头的调度到admin.site.urls中
    url(r'^index/',index),  #同上
    url(r'^$',index),
]

构建结果如下

Django 基础

3 模板操作(DTL)

https://docs.djangoproject.com/en/2.2/ref/templates/builtins/

1 变量

语法 {{variable}}

变量名由字母,数字,下划线,点号组成


点号使用时,需要遵循的顺序:
1 字典查找,如foo['bar'],把foo当做字典,bar当做key
2 属性或方法的查找,如foo.bar 是把foo当做对象,bar当做属性或者方法
3 数字索引查找,如foo[bar],把foo当做列表一样,将使用索引访问


如果变量未能找到,则缺省插入空字符串

在模板中调用方法,不能加小括号,自然也不能传递参数

{{ my_dict.keys }} 这样是对的,不能写成 {{ my_dict.keys() }}

2 模板标签

1 if/else 标签

基本语法如下
{% if condition %}
... display
{%end%}

或者
{% if condition1 %}
..display 1
{% elif condition2 %}
...display 2
{% else %}
...display 3
{% endif %}

条件也支持and,or,not
注意:因为这些标签是断开的,所以不能像python一样使用锁紧就可以表示出来,必须有一个结束表亲,如 endif endfor

2 for 标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<ul>
    {% for  x  in  name %}
    <li>  {{ x }}   </li>
    {% endfor %}
</ul>

</body>
</html>

下面是便利字典的值

    return  render(request,'index.html',{'name':dict(zip('abcd',range(4)))})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<ul>
    {% for  x  in  name.values %}  
    <li>  {{ x }}   </li>
    {% endfor %}
</ul>

</body>
</html>

结果如下

Django 基础

变量 说明
forloop.counter 当前循环从1开始计数
forloop.counter 0 当前循环从0开始计数
forloop.revcounter 从循环的末尾开始倒计数到1
forloop.revcounter0 从循环的末尾开始倒计数到0
forloop.first 第一次进入循环
forloop.last 最后一次进入循环
forloop.parentloop 循环嵌套时,内存当前玄幻的外层循环
    return  render(request,'index.html',{'name': [1,2,3,4,5,6]})

翻转,此处仅限于列表

<ul>
    {% for  x  in  name  reversed  %}
    <li>  {{ x }}  </li>
        {% empty %}
        <li>  default  </li>
    {%endfor%}
</ul>

empty ,为空或者不存在时执行此命令

如下

<ul>
    {% for  x  in  mysql  reversed  %}
    <li>  {{ x }}  </li>
    {% empty %}
    <li>  default </li> 
    {%endfor%}
</ul>

此处的mysql是不存在的,因此下面的结果是

Django 基础


后端代码如下

    return  render(request,'index.html',{'name': dict(zip('abcd',range(4)))})
<ul>
    {% for  k,v  in  name.items %}
    <li>   {{ forloop.first }} </li>
    <li>   {{ forloop.last  }} </li>
    {%endfor%}
</ul>

<h1> 分割线 </h1>

<ul>
    {% for  k,v  in  name.items %}
    <li>   {{ forloop.counter}} {{ k }}   {{ v }} </li>
    {%endfor%}
</ul>

<h1>  分界线 </h1>

<ul>
    {% for  k,v  in  name.items %}
    <li>   {{ forloop.counter0 }} {{ k }}   {{ v }} </li>
    {%endfor%}
</ul>

结果如下

Django 基础

3 ifequal/ifnotequal 标签

{% ifequal %} 标签比较两个值,当其相等时,显示在其标签之间的所有值,

{%ifequal user currentuser %}
<h1> welcome! </h1>
{% endifequal %}

和{% if %}类似,{% ifequal %} 支持可选的 {% else %}标签。


后端代码如下

    return  render(request,'index.html',{'name': 'mysql'})

显示层代码如下

{% ifequal  name  'mysql' %}
    <h1> Site </h1>
{%else%}
<h1>Not Site </h1>
{%endifequal%}
</body>
</html>

Django 基础

4 其他标签

csrf_token 用于跨站请求伪造保护,防止跨站***的

{% csrf_token%}

3 注释标签

单行注释

{#这是一个注释#}

多行注释

{% comment %}
这是多行注释
{%endcomment%}

4 过滤器

模板过滤器可以在变量被显示之前修改它

语法 {{ 变量 | 过滤器 }}

过滤器使用管道符 | , 例如 {{name| lower}} , {{name}} 变量被过滤器 lower 处理后,文档大写转换文本为小写。

过滤管道可以被套接,一个过滤器管道的输出又可以作为下一个管道的输入,例如{{my_list | first | upper }},将列表第一个元素并将其转换为大写。

过滤器传递参数
有些过滤器可以被传递参数,过滤器的参数跟随冒号之后并且总是以双引号包含

如 {{bio| trunactewords:"30"}},截取显示变量的bio的前30个词。
{{my_list | join:"."}}将my_list的所有元素使用逗号连接起来

过滤器 说明 举例
first 取列表第一个元素
last 去列表最后一个元素
yesno 变量可以是 True,False,None,yesno的参数给定的逗号分隔的三个值,返回3个值中的一个。True对应飞一个,False对应第二个,None对应第三个,如果参数只有2个,则None等效于False处理 {{value yesno:"yeah,no,maybe"}}
add 加法,参数是负数就是减法 数字加{{value add:"100"}} 列表合并{{mylist add:newlist}}
divisibleby 能否被整除 {{vaule divisibleby:"3"}}能够被3整除返回True
addslashes 在反斜杠,单引号或者双引号前面加上反斜杠 {{value addslashes}}
length 返回变量的长度 {% if my_list length >1 %}
default 变量等价False则使用缺省值 {{value default:"nothing"}}
default_if_none 变量为None使用缺省值 {{value default_if_none:"noting"}}

练习

计数返回一种类型的值,偶数返回一种类型的颜色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<u1>
{% for  v  in  name.values %}
    {% if   forloop.counter0|divisibleby:"2" %}
    <li style="color:red"> {{  v  }} </li>
    {% else %}
    <li style="color:seagreen">  {{ v }} </li>
    {% endif %}
{% endfor %}
</u1>
</body>
</html>

第二种

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<u1>
{% for  v  in  name.values %}
    <li style='color: {{ forloop.counter0 | divisibleby:"2"| yesno:"red,blue"}}'>{{v}}</li>
{% endfor %}
</u1>
</body>
</html>

结果如下

Django 基础

四 模型操作

1 管理器对象

Django 会为模型提供一个object对象,其是Django.db.models.manager.Manager类型,用于与数据库交互,当定义模型类的时候没有指定管理器,则Django会为模型类提供一个object管理器。

如果在模型中手动指定管理器后,Django不在提供默认的object管理器了

管理器是Django的模型进行数据库查询操作的接口,Django应用的每一个模型都至少拥有一个管理器。

Django 基础

2 查询

1 查询集

查询会返回结果的集,是Django.db.models.query.QuerySet类型
其是惰性求值,和sqlalchemy一样,结果就是查询的集。
其是可迭代对象。


1 惰性求值:
创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库,在迭代,序列化,if语句中都会立即求值。

2 缓存
每一个查询都包含一个缓存,来最小化对数据库的访问
新建查询集,缓存为空,首次对查询集请求值时,会发生数据查库查询,Django会把查询的结果缓存在这个缓存中,并返回请求的结果,接下来对查询集的求值将使用缓存的结果。


观察下面2个例子是要看真正生成的语句了

1 没有使用缓存,每次都要查询数据库,查询了两次
[user.name for user in User.objects.all()]
[user.name for user in User.objects.all()]

2 下面的语句使用缓存,因为其使用同一个结果集
qs = User.objects.all()

[user.name for user in qs ]
[user.name for user in qs ]

2 限制查询集(切片)

查询集对象可以直接使用索引下表的方式(不支持负向索引),相当于SQL语句中的limit 和 offset 字句,注意使用索引返回的新结果集,依然是惰性求值,不会立即查询。


qs = User.objects.all()[20:40]

SQL 等价:Limit 20 offset 20

qs = User.obeject.all()[20:30]

SQL 等价:Limit 10 offset 20

3 过滤器

column column
all() Text
filter() 过滤,返回满足条件查询的数据
exclude() 排除,排除满足条件的数据
order_by()
values() 返回一个对象的字典的列表,像JSON

下属等价
filter(k1=v1).filter(k2=v2)等价于 filter(k1=v1,k2=v2)
filter(pk=10)这里pk指的是主键,不用关心主键的名字字段,当然也可以使用主键来进行相关的过滤操作


返回单值的情况

column column
get() 仅返回单个满足条件的对象,如果未能返回对象则排除DoesNotExists异常,如果能返回多条,抛出MultipleObjectReturned 异常
count() 返回当前查询的总条数
first() 返回第一个对象
last() 返回最后一个对象
exist() 判断查询集中是否有数据,如果有则返回True

字段查询(field Lookup) 表达式
字段查询表达式可以作为filter(),exclude(),get() 的参数,实现的是where字句的功能

语法: 属性(字段) 名称_比较运算符=值
注意: 属性名和运算符之间使用双下划线

column column
exact filter(isdeleted=False) filter(isdeleted__exact=False) 严格等于,可以省略不写
contains exclude(title__contains='天') 是否包含,大小写敏感,等价于 like '%天%'
startswith endswith filter(title__startswith='天') 以什么开头,以什么结尾,大小写敏感
isnull isnotull filter(title__isnull=False) 是否为null
iexact,iconains,istartswitch,iendswith i 的意思是忽略大小写
in filter(pk__in=[1,2,3,4]) 是否在指定返回的数据中
gt,gte,lt,lte filter(id__gt=3) filter(pk__ltd=3),filter(pub_date__gt=date(2000,1,1)) 大于,小于等
year,month,day,week_day,hour,minute,second filter(pub_date__year=2000) 对日期类型属性处理

4 Q对象

虽然Django 提供传入条件的方式,但是不方便,它还提供了Q对象来解决。

Q对象是Django.db.modules.Q,可以使用 &(and) , |(or)操作符来组成逻辑表达式,~ 表示not

from django.db.models  import Q 
User.objects.filter(Q(pk__lt=6))  # 不如直接写 User.objects.filter(pk<6)

User.objects.filter(pk__gt=6).filter(pk_lt=10)  #与 
User.objects.filter(Q(pk__gt=6) &  (pk__lt=10))  # 与 

User.objects.filter(Q(pk=6) | Q(pk=10))  # 或 
User.objects.filter(~Q(pk__lt<6))  # 非

可使用&| 和Q对象来构造复杂的逻辑表达式
过滤器函数可以使用一个或多个Q对象
如果混用关键字参数和Q对象,那么Q对象必须位于关键字参数的前面,所有参数都将and在一起

3 创建表字段操作

1 模型选项

字段类 说明
AutoField 自增的整数字段,如果不指定Django会为模型类型自动增加主键字段
BooleanField 布尔值字段,True和False,对应表单控件CheckboxInput
NullBooleanField 比BooleanField 多一个空值
CharField 字符串,max_length 设定字符串长度,表单控件TextInput
TextField 大文本字段,一般超过4000个字符使用,对应表单控件Textarea
IntegerField 整数字段
BigIntegerField 更大整数字段,8字节
DecimalField 使用Python的Decimal实例表示十进制的浮点数,max_digits 总位数,decimal_places 小数点后的位数
FloatField python中的Float实例表示的浮点数
DateField 使用python的datetime.date 实例表示的日期,auto_now=False每次修改对象自动设置为当前时间,auto_now_add=False对象第一次创建时自动设置为当前时间,auto_now_add,auto_now,default互斥,对应控件为TextInput,关联了一个js编写的日历控件
TimeField 使用python的datetime.time实例表示时间,参数同上
DateTimeField 使用python的datetime.datetime实例表示的时间,参数同上
FileField 一个上传文件的字段
ImageField 继承了FileField 的所有属性和方法,但是对上传文件进行校验,确保是一个有效的图片

2 字段选项

说明
db_column 表中字段的名称,如果未指定,则使用属性名
primary_key 是否为主键
unique 是否是唯一
default 缺省值,这个缺省值不是数据库字段的缺省值,而是新对象产生的是够被填入的缺省值
null 表的字段是否可以为null,默认为False
db_index 字段是否有索引

3 关系类型字段类

说明
ForeignKey 外键,表示一对多 ForeignKey('production.Manufacturer')自关联 ForeiginKey('self')
ManyToMaryField 表示多对多
OneToOneField 表示一对一

一对多时,自动创建会增加_id后缀。

从一访问多,使用 对象.小写模型类_set
从一访问一,使用 对象.小写模型类
访问 id 对象.属性_id

4 创建User的Model 类

基类 models.Model
表名不指定默认使用<appname>_<model_name>,使用Meta类修改表名

Django 基础

相关代码如下

from django.db import models
# Create your models here.
class User(models.Model):
    class Meta:
        db_table='user'  # 定义数据库表名
    id = models.AutoField(primary_key=True)  # 定义主键自增字段
    name=models.CharField(max_length=48,null=False)  # 定义name为浮点型,且其不能为空
    email=models.CharField(max_length=64,unique=True,null=False)  # 定义邮件为浮点类型,且其必须唯一,不能为空
    password=models.CharField(max_length=128,null=False) # 定义密码类型,其为浮点数,且不能为空
    def __repr__(self):
        return   '<user  {}  {}>'.format(self.id,self.name)
    __str__=__repr__

迁移 migration

迁移:从模型定义生成数据库的表
1 在项目根目录执行下面文件生成迁移文件

 python manage.py makemigrations

结果如下

Django 基础

修改过Model类,还需要调用makemigrations,然后migrate,迁移文件的序号会增加

注意:迁移的应用必须在settings.py 的 INSTALLED_APPS 中注册


2 在项目的根目录执行迁移生成数据库的表

python  manage.py migrate

结果如下

Django 基础

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章