Django
Django是python的一个开放源代码的Web应用框架
Web框架---MVC,MTV
MVC
一种设计典范,用一种业务逻辑,数据,界面显示分离的方法组织代码
-
Model:应用程序数据逻辑部分,在数据库中存取数据
-
View:数据显示部分,依据Medel创建
-
Controller:用户交互部分
MTV
MTV与MVC的本质没有差别,django就应用了MTV模式
-
Model:与数据库交互
-
View:业务逻辑处理
-
Template:页面显示
-
URL分配器:将用户的URL分发给不同的View处理
Django
创建Django项目
- django-admin startproject djangoNote:在命令模式下进入你想要创建项目的目录,然后输入这个命令即可,如果提示django-admin不是内部命令的话,只需要配置一下系统环境变量即可
- __init__.py:告诉python这个目录可以看做一个python包
- settings.py:项目的配置文件
- urls.py:项目的URL声明
- wsgi.py:与WSGI兼容的Web服务入口
- manage.py:命令行工具,可以与django项目进行交互
配置数据库
django默认使用的数据库是sqlite,如果想使用mysql,需要在settings.py的BATABASE里按下面格式配置数据库,然后在我们创建的项目下的__init__.py中加入:
import pymysql
pymysql.install_as_MySQLdb()
1 'default': { 2 'ENGINE': 'django.db.backends.mysql', 3 'NAME': '数据库名', 4 'PASSWORD':'密码', 5 'USER':'用户名', 6 'HOST':'主机', 7 'PORT':'端口' #默认为3306 8 }
创建应用
- python manage.py startapp 应用名称:进入有manage.py的文件里,然后再命令窗口可以输入命令就可以创建,在一个项目中可以创建多个应用,每个应用进行一种业务处理
- 在settings配置文件的INSTALLED_APPS中加入我们的创建应用
INSTALLED_APPS = [ ..... , 'myApp', ]
-
admin.py:站点配置等相关信息
-
models.py:模型,与数据库交互部分
-
views.py:视图,业务处理
启动服务器
- python manage.py runserver ip:port :ip可以不写,不写的话代表本机ip,端口默认为8000
Model
models.py是与数据库交互的部分,在这里我们可以创建类,一个类代表数据库中的一张表,而且我们可以不定义主键,它会为我们自动定义
ORM:对象-关系-映射,ORM让我们不用因数据库的变更而修改代码
- 根据对象的类型生成表结构
- 将对象、列表的操作转换为sql语句
- 将sql语句查询到的结果转换为对象、列表
开发流程
- 配置数据库
- 定义模型类
- 生成迁移文件:python manage.py makemigrations
- 执行迁移生成数据表:python manage.py migrate
- 使用模型类进行增删改查(crud)操作
迁移文件生成成功之后,在数据库中就可以看到一些自动生成的表了
如果我们想要自定义数据库中的表名,那么我们就需要在模型类中定义Meta类,用于设置元信息,然后需要删除迁移文件,删除数据库表,重新生成
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class myFriend(models.Model): 2 fName = models.CharField(max_length=20) 3 fSex = models.BooleanField(default=True) 4 fAge = models.IntegerField() 5 fSingle = models.BooleanField(default=True) 6 class Meta: 7 db_table="myfriend" #定义数据库中的表名 8 ordering=["id"] #定义排序,id为升序,-id为降序 9
Model中的字段类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 AutoField:·一个根据实际ID自动增长的IntegerField,通常不指定如果不指定,一个主键字段将自动添加到模型中 2 3 CharField(max_length=字符长度),字符串,默认的表单样式TextInput 4 5 TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea 6 7 IntegerField:整数 8 9 DecimalField(max_digits=None, decimal_places=None)使用python的Decimal实例表示的十进制浮点数 10 ·参数说明 11 ·DecimalField.max_digits 12 ·位数总数 13 ·DecimalField.decimal_places 14 ·小数点后的数字位数 15 16 FloatField:用Python的float实例来表示的浮点数 17 18 BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput 19 20 NullBooleanField:支持null、true、false三种值 21 22 DateField([auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示的日期 23 ·参数说明 24 ·DateField.auto_now 25 ·每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false 26 ·DateField.auto_now_add 27 ·当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false 28 ·说明 29 ·该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的invalid_date错误消息键 30 ·注意 31 ·auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果 32 33 TimeField:使用Python的datetime.time实例表示的时间,参数同DateField 34 35 DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField 36 37 FileField:·一个上传文件的字段 38 39 ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ·null 2 ·如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False 3 4 ·blanke 5 ·如果为True,则该字段允许为空白,默认值是 False 6 7 ·注意 8 ·null是数据库范畴的概念,blank是表单验证证范畴的 9 10 ·db_column 11 ·字段的名称,如果未指定,则使用属性的名称 12 13 ·db_index 14 ·若值为 True, 则在表中会为此字段创建索引 15 16 ·default 17 ·默认值 18 19 ·primary_key 20 ·若为 True, 则该字段会成为模型的主键字段 21 22 ·unique 23 ·如果为 True, 这个字段在表中必须有唯一值
类属性
- objects:Manager类型的一个对象,作用是与数据库进行交互,如果没有指定管理器,那么自动生成objects管理器,如果指定了管理器,那么objects就无效了
- 自定义管理器manager类:需要继承model.Manager,可以重写get_queryset()方法修改管理器返回的原始查询集,然后再某个类中创建这个manager类的对象即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class myManager(models.Manager): 2 def get_queryset(self): 3 return super(myManager,self).get_queryset().filter(fSingle=True)
查询数据集
- 过滤器:返回查询集的方法
- all:返回查询集中所有的数据
- filter:返回符合条件的数据
- filter(键=值)
- filter(键=值, 键=值)
- filter(键=值).filter(键=值)
- exclude:过滤掉符合条件的数据
- order_by:排序
- values:返回一个列表,一条数据就是一个对象(字典)
- 返回单条数据
- get:返回满足条件的一个对象,如果没有找到或者找到多条数据都会发生异常
- frist:返回数据集中的第一个对象
- last:返回数据集中的最后一个对象
- count:返回数据集中对象的个数
- exists:判断数据集中是否有数据,有数据返回True
- 限制数据集:利用下标的方法限制,例如xxx.管理器对象.all()[startNum,endNum]
- 字段查询
语法:属性名称__比较运算符=值
外键:属性名_id
比较运算符
-
- exact:判断,大小写敏感,例如:filter(isSingle=False)
- contains:是否包含,大小敏感,icontains不区分大小写
- startswitch,endswitch:为value开头或者结尾的,大小写敏感,如果在前面加 i 则不区分大小写,例如:friendsList = myFriend.objects.filter(fName__startswith="陈"),以下的用法一样
- in:是否包含在某一个范围
- gt:大于
- gte:大于等于
- lt:小于
- lte:小于等于
- year:年
- month:月
- day:日
- hour:时
- minute:分
- second:秒
- pk:主键
聚合函数
使用aggregate()函数返回聚合函数的值,要使用聚合函数的话需要导入from django.db.models import 聚合函数名
- Avg
- Count
- Max
- Min
- Sum
用法:maxAge = myFriend.objects.aggregate(Max('fage'))
F对象
F对象的出现是为了让一个模型类的属性之间能够进行比较,需要导入from django.db.models import F
格式:类名.管理器名.filter(属性A__比较运算符=F('属性B')),例如Grades.objects.filter(ggirlnum__gt=F('gboynum'))
Q对象
Q对象是为了让过滤器能够进行或查询
格式:类名.管理器名.filter.(Q(条件一)|Q(条件二)...),例如:studentsList = Students.objects.filter(Q(pk__lte=3) | Q(sage__gt=50))
如果在Q对象前面加~,那么表示取反
View
业务处理,对于用户的每一个URL请求,相对应的有一个处理函数,这就是视图,在views,py中定义
由于一个工程下面可能不只用一个应用,而视图是根据用户输入的URL来做出相对应的处理,因此我们可以在该应用下面创建一个urls.py文件,用来处理该应用的URL请求,这时只需要在根URL分发器中包括该应用的创建的url即可,在settings.py中的ROOT_URLCONF可以知道哪个为根URL分发器
ROOT_URLCONF = 'djangoNote.urls'
在根URL上加入我们应用的url即可:
urlpatterns = [ url(r'^admin/', admin.site.urls), #根URL url(r'^',include('myApp.urls.py')) #应用的URL,注意用.连接 ]
然后在应用的urls中定义用户输入的url对应的视图中的函数即可:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$',views.index) ]
视图views.py中函数:
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse("欢迎来到index")
错误视图(以404为例)
找不到网页(url匹配不成功)时返回,404定义在template目录下,必须命名为404.html,利用request_path可以获取导致错误的网址
然后需要在settings文件中配置才可以使用404视图,在此之前我们还需要设置一下template的路径,在settings中的配置TEMPLATE中的DIRS加入template目录的路径:
os.path.join(BASE_DIR,'template')
DEBUG = False #如果为True永远不会调用404.html页面 ALLOWED_HOSTS = ['*']
HttpRequest对象
HttpReques对象是服务器接受到http请求后,根据报文创建的对象,视图的第一个参数都是HttpRequest对象
属性:
- path:请求的完整路径(不包括域名和端口)
- method:请求的方式,GET或POST
- encoding:浏览器提交数据的编码方式
- GET:类似字典的对象,包含get请求的所有参数
- get方法:根据键获取值,只能获取一个
- getlist()方法:根据键获取值,值以列表的形式返回,可以获取多个
- POST:类似字典的对象,包含post请求的所有参数,POST也有get和getlist方法
- COOKIES:字典,包含所有的cookie
- session:类似字典的对象,表示当前会话
HttpResponse对象
给浏览器返回数据
- 不调用模板,直接用HttpResponse("返回内容")
- 调用模板:使用render方法
- render(request, templateName[, context])
- request:请求体对象
- templateName:模板路径
- context:需要渲染在模板上的数据
- render(request, templateName[, context])
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def showFriends(request): 2 friendList=Friends.objects.all() 3 return render(request,"myApp/friends.html",{"friends":friendList}) #将friendList传到friends.html中的friends 4 5 6 friends.html 7 8 <ul> 9 {% for foo in friends %} 10 <li> 11 <a href="#">{{ foo.fName }}</a> 12 </li> 13 {% endfor %} 14 15 </ul>
属性:
- content:返回的内容
- charset:编码格式
- status_code:响应状态码
- content-type:指定输出的MIME类型
方法:
- init:使用页面内容实例化HttpResponse对象
- write(content):以文件的形式写入
- flush:以文件形式输出到缓冲区
- set_cookie(key, value='', max_age=None,exprise=None):设置cookie
- delete_cookie(key):删除cookie
重定向:
服务器端的跳转,需要导入from django.http import HttpResponseRedirect或者from django.shortcuts import redirect
用法:
- HttpResponseRedirect(“重定向后的网页”)
- redirect(“重定向后的网页”)
状态保持
http是无状态的,每一次连接都不会记得上一次连接做过什么,因此我们要实现状态保持的话,需要借助cookie或者session
-
cookie:http协议时无状态的,每次请求都是一次新的请求,不记得以前的请求
-
session:所有的数存储在服务端,在客户端用cookie存储session_id,每一个Httprequest对象都有一个session属性
启用session需要在配置文件中:
INSTALLED_APPS = [ ... 'django.contrib.sessions', ... ] MIDDLEWARE = [ ... 'django.contrib.sessions.middleware.SessionMiddleware', ... ]
session方法:
- get(key,default=None):根据键获取session值,例如request.session.get('name',"没找到吧"),如果没有找到name,那么就放回“第二个参数的值”,如果是要存的话,request.session['name'] = username
- clear:清空所有的会话
- flush:删除当前的会话并删除会话的cookie
- set_expiry(value):设置过期时间,默认为两星期
- 0:关闭浏览器是失效
- None:永不过期
URL反向解析
URL反向解析是为了在url配置发生改变时,动态生成链接的地址,否则一旦修改了URL配置,所有的地方都需要相对应的修改,主要通过namespace和name来实现,在使用链接时,通过url配置的名称,动态生成url地址
根URL:
urlpatterns = [ ... url(r'^',include('myApp.urls',namespace='app')) ]
应用URL
urlpatterns = [ ... url(r'^urlRerverse/$',views.urlRerverse,name='rerverse') ]
HTML中
<a href="{% url "app:rerverse" %}">跳</a>
Template
在与应用同级的目录下创建一个template目录,并且配置settings文件中TEMPLATE的DRIS=[os.path.join(BASE_DIR,'template')],这个目录主要用来存放要显示的视图
模板由HTML代码和逻辑代码组成
逻辑代码有两种写法
- {% 标签 %}
- if:与python中的if用法一样,只是要包在{% %}里面,且最后需要加{% endif %}
-
1 形式一: 2 {% if 表达式 %} 3 语句 4 {% endif %} 5 6 形式二: 7 {% if 表达式1 %} 8 语句1 9 {% else%} 10 语句2 11 {% endif %} 12 13 形式三: 14 {% if 表达式1 %} 15 语句1 16 {% elif 表达式2 %} 17 语句2 18 …… 19 {% elif 表达式n %} 20 语句n 21 {% else %} 22 语句e 23 {% endif %}
- for:与python中的for用法一样,只是要包在{% %}里面,且最后需要加{% endfor %}
-
1 形式一: 2 {% for 变量 in 列表 %} 3 语句 4 {% endfor %} 5 6 形式二:列表为空或者列表不存在时执行语句2 7 {% for 变量 in 列表 %} 8 语句1 9 {% empty %} 10 语句2 11 {% endfor %} 12 13 特殊:表示当前是第几次循环 14 {{ forloop.counter }}
- comment:用来多行注释
-
1 {% comment %} 2 .......... 3 {% endcomment %}
- ifequal、ifnotequal:等于,不等于
-
1 {% ifequal 'A' 'B' %} 2 <h1>same</h1> #如果A=B,则执行 3 {% endifequal %}
- include:加载模板并以标签内的参数渲染,{% include '模板目录' 参数1 参数2 %}
- url:用来URL的反向解析
-
1 <a href="{% url "namespace名:name名" %}">跳</a>
- csrf_token:用于跨站请求伪造保护
- block、extends:用于模板的继承
-
1 在父模板上利用block空出位置: 2 <h1>反转了。。。</h1> 3 4 <div> 5 {% block body %} 6 7 {% endblock %} 8 </div> 9 10 <h2>反转2了。。。</h2> 11 12 继承上面的模板 13 {% extends "父模板路径l" %} 14 {% block body %} 15 <h1>haha</h1> 16 {% endblock %}
- autoescape:用于HTML的转义
- {{ var|过滤器 }}
- lower:变小写
- upper:变大写
- join:连接,可带参数,例如<h1>{{list | join:'@'}}</h1>
- date:根据给定格式转换日期为字符串,例如{{ dateVal|date:'y-m-d'}}
- default:如果一个变量没有被提供,或者值为false、空,可以使用默认值,例如:<h1>{{test | default:'没有'}}</h1>
- 加减乘除
-
1 <h1>{{ num|add:5 }}</h1> #加5 2 <h1>{{ num|add:-5 }}</h1> #减5 3 4 <h1>{% widthratio num 1 5 %}</h1> #乘于5 5 <h1>{% widthratio num 5 1 %}</h1> # 除于5
站点管理
站点管理是为了方便内容的添加、修改、删除
-
python manage.py createsuperuser:创建管理员账户,那么我们就可以登录了
如果我们需要汉化的话需要在settings文件中修改配置:
LANGUAGE_CODE = 'zh-Hans' TIME_ZONE = 'Asia/Shanghai'
自定义管理页面
- 定义类
- 列表页属性
- list_display:显示字段
- list_filter:过滤字段
- search_fields:搜索字段
- list_per_page:分页
- 添加修改页属性
- fields:属性的先后顺序
- fieldsets:给属性分组,与fields不能同时使用
- 列表页属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class studentInfo2(admin.StackedInline): 2 model = Student 3 extra = 2 4 5 @admin.register(Grades) 6 class gradesAdmin(admin.ModelAdmin): 7 #在班级的添加删除页里可以添加关联的学生信息 8 inlines = [studentInfo2] 9 10 #自定义显示字段 11 list_display = ["gname","gdate","ggrilnum","gboynum","isDelete"] 12 #一页5条 13 list_per_page = 5 14 list_filter = ["gname"] 15 search_fields = ["gname"] 16 actions_on_bottom = True 17 actions_on_top = False 18 19 # 属性先后顺序 20 # fields = ["ggrilnum","gboynum","isDelete","gname","gdate"] 21 22 #分组 23 fieldsets = [ 24 ("数量",{"fields":["ggrilnum","gboynum"]}), 25 ("基本信息",{"fields":["gname","gdate","isDelete"]}), 26 ]
- 注册类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 第一种: 2 admin.site.register(Student,studentAdmin) 3 4 第二种:下面的代码也是boolen类型的解决问题 5 @admin.register(Student) 6 class studentAdmin(admin.ModelAdmin): 7 def gender(self): 8 if self.sgender: 9 return "男" 10 else: 11 return "女"
静态文件的引入
静态目录的引进,通常在与manager.py同级的目录下创建一个static目录,然后创建每一个应用文件,在这些文件下创建对应得静态文件目录
修改settings文件:
STATIC_URL = '/static/' # 普通文件 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ]
应用:
{% load static from staticfiles %} <link rel="stylesheet" type="text/css" href="{% static 'myApp/css/h1css.css' %}"> <script src={% static 'myApp/js/myJS.js' %}></script>
中间件
一个轻量级、底层的插件,可以介入Django的请求和响应,其实也就是python的一个类
在django中,settings文件中MIDDLEWARE中定义的都是中间件,如果我们自定义中间件的话,也需要添加到这里:
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 ]
中间件可以定义6个函数:
- __init__:不需要传参数,服务器响应第一个请求的时候自动调用,用于确定是否启用该中间件
- process_request(self,request):在分配URL匹配视图之前,每一个请求上都会调用,返回None或者HttpResponse对象
- process_view(self,request,view_func,view_args,view_kwargs):在调用视图之前执行,每一个请求都会调用,返回None或者HttpResponse对象
- process_template_response(self,request,response):在视图刚执行完的时候调用,每一个请求都会调用,返回None或者HttpResponse对象
- process_response(self,request,response):所有响应返回浏览器之前调用,每一个请求都会调用,返回None或者HttpResponse对象
- process_exception(self,request,exception):出现异常的时候,返回HttpResponse对象
自定义中间件
在与manager.py同级的目录下创建一个middleware目录,在其下面创建自己的应用,也需要在settings文件中MIDDLEWARE添加我们的中间件