Django基础
1、简介
Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。
Django是一个处理网络请求的webweb应用框架
Django是开源的
Django有四个核心组件:
- 数据模型和数据库之间的媒介ORM
- 基于正则表达式的URL分发器
- 视图处理系统
- 模板系统
2、特点
1) 强大的数据库功能:用python的类继承,几行代码就可以拥有一个动态的数据库操作API,如果需要也能执行SQL语句。
2) 自带的强大的后台功能:几行代码就让网站拥有一个强大的后台,轻松管理内容。
3) 优雅的网址:用正则匹配网址,传递到对应函数。
4) 模板系统:强大,易扩展的模板系统,设计简易,代码和样式分开设计,更易管理。
5) 缓存系统:与memcached或其它缓存系统联用,表现更出色,加载速度更快。
6) 国际化:完全支持多语言应用,允许你定义翻译的字符,轻松翻译成不同国家的语言
3、安装
使用pip工具来安装Django,直接通过下面命令来安装就可以。
#pip install Django
用一下测试django是否安装成功:
python
>>> import django
>>> print(django.VERSION)
(1, 11, 5, u'final', 0)
4、创建项目
首先,我们先通过django来创建一个项目,命令如下:
#django-admin startproject firstproject
然后在当前目录下就自动生成了一个firstproject的项目,之后就可以启动这个项目了:
#python manage.py runserver 127.0.0.1:8080
默认不写ip绑定的是本机的所以ip地址,端口默认为8000
也可以通过在pycharm中直接创建一个Django项目,就自动创建好了文件,然后配置manage.py脚本的参数。直接运行manage.py文件就好。
然后访问url:http://127.0.0.1:8080,会有一个欢迎的首页
项目目录结构:
第一层:firstproject 项目名称
第二层: firstproject目录和__init__.py文件,声明是一个包,表示项目实际的python包,不要随意更改该目录,与配置有关联
- settings.py:项目的全局配置中心
- urls.py:项目的url配置中心
- wsgi.py:项目的wsgi配置中心
- templates:模板目录
- manage.py:django命令管理脚本
5、创建app
什么叫app呢,app到底有什么作用呢?
打个比方,某网站上面有linux课程,python课程,web前段课程,用户登录,论坛讨论等这些不同的模块,那我们就需要在django里面创建不同的app。
创建app流程:
如果是命令行模式:
#python manage.py startapp linux
#python manage.py startapp python
如果是pycharm,你就需要点击:Tools->>Run manage.py Task
然后出现的交互命令行上输入:
startapp linux
就出现了linux的模块
6、Django的解析顺序
- 既然我们知道Django是使用的MVC的架构,那我们先来聊聊MVC是什么样的原理,首先,通过MVC中的C就是control,用来接收url请求,对应我们django中的url.py模块,M就代表Model,调用数据库的Model层,就是Django的model.py模块,然后经过业务逻辑层的处理,最后渲染到前端界面。前端就是MVC中的view层,对应django的view模块。
- 其实所有的参数定义都是以setting.py为准,首先django先去setting.py中找到ROOT_URLCONF = 'firstproject.urls'找到总url。然后在firstproject下的urls.py文件中的urlpatterns列表变量,然后根据里面的URL的正则表达式进行解析,如果解析到,就调用第二个参数,第二个参数对应一个类或者一个函数,或者直接是一个前端页面,在经过类或者函数处理完以后,在展现在前端界面。而前端是单独的html文件,前端界面和后端处理分开,架构更加清晰。
- 在上面的目录结构中,每一个app都会有一个view.py, model.py,我们自己还要在创建一个url.py,通过include函数,在firstproject项目中的总url.py分出去,把属于各自的app的url分配到不通的APP的urls.py文件中,这样可以降低耦合度,增加代码的健壮性。
7、创建urls.py和views.py文件
urls作为程序的url入口,支持正则匹配,讲访问的url映射到view中的函数中。为了能调用每个app管理自己的url,我们首先需要在firstproject的urls.py文件中做如下修改:
from django.conf.urls import url
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
url('linux/', include('linux.urls')), #定义下属代理
]
注意事项:
- 为了避免和别的app取同样的名字,一般我们会在名字前加一个app名称作为前缀
- url匹配,主url不需要/反斜杠:因为django已经给域名加了一个反斜杠,如:http://127.0.0.1/
- 主url后面要加/, app的url前面就不需要加/了,主url后面一般不要加$符号, app的url后面要加$符号
然后在创建linux/urls.py文件,编辑如下:
from django.conf.urls import url
from linux import views
urlpatterns = [
url(r'^$', views.index, name='index'), #定义linux首页
]
而以上:http://127.0.0.1:8080/linux的url对应的就是view模块中的index函数,在linux的view.py中定义index函数
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("这个是index页面!")
然后在浏览器上访问:http://127.0.0.1:8080/linux/,如下图所示:
8、urls捕获参数
url参数的捕获有两种方式:
1)、捕获位置参数(可变参数):在url函数中,使用正则表达式()进行捕获参数,然后在view中定义即可。如下所示:
在urls.py中增加如下:
url(r'hello/p1(\w+)p2(.+)/$', views.hello),
在views.py中增加如下:
def hello(request, param1, param2):
return HttpResponse("hello {0},hello {1}".format(param1, param2))
然后我们在浏览器上访问url:http://127.0.0.1:8080/linux/hello/p1lingp2xiang/
如下图所示:
url中传入参数ling和xiang,最后直接在界面中打印出来
2)、捕获关键字参数:在url函数中,正则表达是用(?P<keyword>)进行捕获,然后在views.py中定义即可
在urls.py中增加如下:
url(r'keyword/(?P<ip>\S+)/$', views.keyword),
在views.py中增加如下:
def keyword(request, ip):
return HttpResponse("the ip is {0}".format(ip))
在浏览器上访问url:http://127.0.0.1:8080/linux/keyword/1.1.1.1/,如下图所示:
9、url重定向
在学习url重定向之前,我们先来看看定义url的函数是怎样一个表达形式
def url(regex, view, kwargs=None, name=None):
- regex:url匹配的正则字符串
- view:一个可以调用的类型函数,或者使用include函数
- kwargs:关键字参数,必须是一个字典,可以通过这个传递更多参数给views.py,views通过kwargs.get(“key”)得到对应的value
- name:给URL取得名字,以后可以通过reverse函数进行重定向
对于kwargs如何传递参数,我们来看一个例子:
在urls.py中增加如下:
url(r'test/$', view=views.test, kwargs={"name": "ling"}, name="test"),
在views.py中增加如下:
def test(request, **kwargs):
return HttpResponse("{0}".format(kwargs.get("name")))
在浏览器上访问url:http://127.0.0.1:8080/linux/test/, 结果如下图所示:
既然已经知道name属性的用法,现在我们就来说重定向,重定向常用name属性来进行重定向
修改urls.py
url(r'^$', views.index, name="index"),
url(r'redirect/$', view=views.redirect, name="redirect"),
修改views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
def redirect(request):
return HttpResponseRedirect(reverse("index"))
在浏览器上访问url:http://127.0.0.1:8080/linux/redirect,直接跳转到http://127.0.0.1:8080/linux/,
10、view编写技巧
11、model编写技巧
models其实就是和数据库相关的操作,是django处理数据的一个特色之处,它包含你的数据库基本字段和数据,通过一些列封装好的api来直接操作数据库,当然你也可以直接写sql语句。
首先你要进行数据库的配置,在firstproject/setting.py中找到如下配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Django默认是使用sqlite3数据库,而现在市场占有率最高的是mysql,我们更改成mysql的配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'firstproject',
'USER': 'django',
'PASSWORD': 'django',
'HOST': '192.168.137.130',
'PORT': '3306',
}
}
在上面的host服务器上启动mysql,并对上面对应的用户进行授权。
django模型的注意事项:
- 模型必须都是在app下的models.py的文件中
- 模型如果需要映射到数据库,所在的app必须被安装
- 模型都必须继承自django.db下的models包的 Model类
需要注意的是在python3中使用mysql报错ModuleNotFoundError: No module named 'MySQLdb'
原因是:
在python2.x中用mysqldb,但是在python3.x中已经不支持那个组件了。
取而代之的是:import pymysql
在项目文件夹下的_init_.py中导入pymysq包
import pymysql
pymysql.install_as_MySQLdb()
一个表对应一个模型,表中的字段对应模型中的属性,映射模型到数据库之前,要提前把数据库给创建好
在linux/models.py里创建一个模型的类
from django.db import models
# Create your models here.
#定义数据库表字段
class Teacher(models.Model):
name = models.CharField(max_length=50)
age = models.IntegerField()
gender = models.CharField(max_length=10)
subject = models.CharField(max_length=50)
telephone = models.CharField(max_length=20)
把模型映射到数据库
①、首先要创建一个映射文件,通过执行以下命令创建
python manage.py makemigrations linux
后面跟linux是指定linux的app,如果什么都不写,泛指所有models
②、将映射文件中的映射数据真正提交到数据库中,执行以下命令:
python manage.py migrate linux
id字段django会自动给我们添加,没有写时自动添加,并自动把id作为主键
注意事项:
如果修改字段或者更改改类,需要重新执行上面的两个命令,但是在pycharm中为了简单执行这两个命令,我们可以做如下设置:
点击Run->Edit Configurations,可以看到我们的django项目,然后点击+号,Name为:makemigrations,选择Custom run command为:makemigrations,Host和Port都为空,如下图所示
如上面以上,我们也创建一个migrate,把上面所有makemigrations替换成migrate即可。
运行makemigrations就相当于运行:
Python manage.py makemigrations
运行migrate就相当于执行如下命令:
Python manage.py migrate
通过在models.py中创建的类,在通过以上两个命令的时候,就被映射到我们数据库中去了,我们只需要创建好表就可以了,创建表,django就自动给我们做好了,而且数据库的操作django已经封装好了,我们只需要通过ORM方式进行调用就可以了。让我们从繁琐的sql语句中解脱出来,更加专注的整理我们的代码逻辑就好了。
12、Django的modules.py
django模型的实用:
- 模型必须都是在app下的models.py的文件中
- 模型如果需要映射到数据库,所在的app必须被安装
- 模型都必须继承自django.db下的models包的 Model类
- 一个表对应一个模型,表中的字段对应模型中的属性
- 映射模型到数据库之前,要提前把数据库给创建好.
- 数据库要提前创建好
创建模型的类
#-*- coding:utf-8 -*-
from __future__ import unicode_linux_linuxtest literals
from django.db import models
class BlogModel(models.Model):
id = models.AutoField(primary_key = True)
title = models.CharField(max_length = 100, null = False)
content = models.TextField(null = False)
test = models.CharField(max_length = 100, null = True)
把模型中的数据映射到数据库
###将模型映射到数据库中:
首先要创建一个映射文件,通过执行以下命令创建:
python manage.py makemigrations book
将映射文件中的映射数据真正提交到数据库中,执行以下命令:
python manage.py migrate book
修改字段以后重新执行,id字段django会自动给我们添加,没有写时自动添加
更改表名:
class ArticleModel(models.Model):
title = models.CharField(max_length = 100, null = False)
content = models.TextField(null = False)
class Meta:
db_table = 'test_xiang‘
在class类下面更改表名,然后执行python manage.py makemigrations和python manage.py migrate,把数据映射到数据库
增加数据:
直接调用定义好的`Model`的`save`方法就可以保存一条数据了,如下所示:
13、模板
在了解模板之前,我们先来了解一下django的请求流程,用户通过客户端发起请求,经过处理,到达urls.py,进行url的匹配,然后传递给后面的views对应的函数来处理,函数根据自己的逻辑,跟models进行交互,然后渲染出界面效果,最终让用户接收。
而为了真正让我们的前段代码和后端代码分离,我们前端的代码要单独的创建一个文件来编写自己的html,css文件等。通过render函数进行前段渲染。
那么在学习模板之前,我们先来看看模板的配置文件,在setting.py中,我们找到TEMPLATES这个配置选项,如下:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
上面代码中的DIRS就代表的是django的查找路劲,默认都不会去改动,APP_DIRS如果是True,模板就会去前面变量INSTALLED_APPPS中已经安装了的app下面templates目录下面自动去查找模板,所有凡是我们增加的app,都需要在一下变量中增加,以方便我们后面编写模板。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'linux',
'python',
]
在linux的目录下面创建templates,然后你就可以根据自己的需要创建文件夹和写自己合适的前端文件。
我自己在templates下面创建了html文件,在html文件下面创建了testtmp.html,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>this is test.</h1>
<p>hello lingxiangxiang</p>
</body>
</html>
from django.shortcuts import render
def index(request):
return render(request, "html/index.html")
14、模板变量
既然我们学习的模板,那就存在前端代码和后端代码进行交互的情况。既然由后端向前端传递参数,就会用到变量,那我们接下来就来看看django的模板变量是怎么用的吧。
- 模板的变量语法:{{变量}}
- 变量的命名:由字母和数字以及下划线组成,不能以空格和标点符号命名。
- 可以使用字典,类,函数,列表等形式传入.
例如:
def testtmp(request):
nameClass = NameClass(name="我爱北京天安门")
return render(request, "html/testtmp.html", context={'name_dict': "参数为字典", "name_fun": lambda : "你妈叫你好好学习函数", "name_class": nameClass, "name_list": ['aa', 'bb', 'cc']})
在testtmp.html文件中增加如下前段代码:
<p>hello {{ name_dict }}</p>
<p>hello {{ name_fun }}</p>
<p>hello {{ name_class.getName }}</p>
<p>hello {{ name_list }}</p>
15、模板过滤器
我们在给前端展示变量的时候,我们的变量可能还需要做一些改动或者过滤,具体怎么过滤呢,我们先来看看过滤器的语法:
{{name|lower|capfirst}}
变量后面跟|,然后在跟过滤函数,直接可以对变量进行过滤。
过滤函数:
default:提供给一个默认值,这个只有在变量为None的时候才使用默认值
hello {{name1|default:"test"}}
add:字符串相加,数字相加,列表相加,如果失败,则会返回一个空字符串
hello {{name|add: name1}}
first:返回列表中的第一个值。
last: 返回列表中的最后一个值
join:跟python中的join一样的用法
length:返回字符串或者是数组的长度。
lower:把所有字符串都编程小写。
capfirst:首字母大写
slice:切割列表。用法跟python中的切片操作是一样的,区间是前闭合后开放
striptags:去掉所有的html标签。
safe:关闭变量的自动转义
16、模板语法
①、标签语法:{%tag%}{%endtag%}
②、if/elif/else:可以使用and/or/in/not/==/!=/<=/>=,来进行判断
③、for…in…:跟python中的for…in…是一样的用法
forloop.counter:当前迭代的次数,下标从1开始。{{}}是打印下标,下标从1开始
forloop.counter0:当前迭代的次数,下标从0开始。打印下标
forloop.revcounter:跟forloop.counter一样,下标从大到小
forloop.revcounter0:跟forloop.counter0一样,下标从大到小
forloop.first:返回bool类型,如果是第一次迭代,返回true,否则返回false
forloop.last:返回bool类型,如果是最后一次迭代,返回True,否则返回False。
forloop.parentloop:如果发生多层for循环嵌套,那么这个变量返回的是上一层的for
④、for…in…empty…:如果没有数据,跳转到empty中
⑤、load:加载第三方标签。最常用的是{%load static%}
⑥、url:返回一个命名了的URL的绝对路径
⑦、with:缓存一个变量
⑧、autoescape:开启和关闭自动转义
17、模板继承
①、{% extends "test.html" %}
继承test.html的html,只能继承一个,必须出现在第一个出现的标签,否则报错
②、使用block模块进行复制模板
③、使用{% include “ling.html” %} 把ling.html包含进来
test.html先定义一个引入新模块的地方
bodyblock是模块的名字,可以自己定义,book.html继承test.html,然后引入ling.html模块
④、注意事项:
a、子模块中的所有内容,必须出现在父模块定义好的block中,否则django讲不会渲染
b、尽可能多的使用标签,方便子模块实现更细的功能
红色的不会启动任何作用,不会显示出来
⑤、子模块如果需要使用父模块的内容,需要在block模块使用{{block.super}}变量
18、注释
{#注释#}:单行注释
{% comment %}......{% endcomment %}:多行注释
19、模板加载静态文件
在setting中,有一个变量叫做STATIC_URL,这个变量会在安装了app下面的static目录下面去加载静态文件。也可以去STATICFILES_DIRS = (static),路径的规则和templates的一样
STATIC_URL = '/static/'
①、加载css
test.html模块进行添加如下两行
因为static是第三方模块,所以需要load一下才可以使用,不然报错,在book的static目录下面创建style.css文件,然后输入如下内容
body{
background:blue;
}
②、加载js
在test.html中加入js模块
然后在myjs.js文件中加入myjs.js的文件,写入如下
prompt(‘hello world’)
③、加载图片
在book.html中加入如下,extends模块必须是第一个变量,否则报错,然后在book/static的目录下放入1.jpg的图片
20、表单
html中用于提交数据给服务器的一个标签,所有的input/textarea/button都放在form标签中
method设置方法:默认是POST
action设置表单提交的URL,如果不写或者保持空字符串,那么表示当前的URL
get方法:从服务器获取数据,不更改数据,在url中携带数据给服务器, 返回html页面
post方法:发送给服务器数据,一般更改服务器的数据,传递的参数不能在url中看到,通过body参数传递给服务器,post相对你get安全
HttpRequest:存储客户端发送过来的数据
HttpResponse:服务器发送返回客户端的响应
①、request.scheme:网络请求的协议,一般是http和https
②、request.body:http请求中传递的原始数据,是一个byte类型的string,如果要处理form表单上传上来的数据,应该使用request.POST,这个处理得比较好
③、request.path:当前请求的URL路径,但是不包括scheme和域名,比如有http://www.myblog.com/blog/1。那么返回的将是/blog/1。会去除掉http和www.myblog.com
④、request.method:当前这个请求访问方法,一般为GET和POST,例如可以通过以下方式进行判断:
* request.GET:一个QueryDict的类字典类型的对象,可以通过访问字典的方式进行访问里面的值,里面的值是通过GET请求传递进来的参数
* request.POST:同request.GET,但是是保存了通过POST请求传递上来的参数。注意,这个POST里面不包含上传的文件信息。如果要访问上传的文件,请使用request.FILES
⑤、request.COOKIES:一个字典类型,包含了所有的cookie信息,key和value都是字符串
⑥、request.META:存储所有请求的头部信息
import json
with open('1.json', 'w') as fp:
json.dump(request.META, fp)
⑦、request.session:返回一个QueryDict的类字典类型的集合,这个属性要有效,必须添加SessionMiddleware这个中间件
⑧、request.is_secure():如果是HTTPS的,那么返回True,否则返回False
⑨、request.is_ajax():这个请求是否是通过XMLHttpRequest进行访问的。**他的实现原理就是去request.META中查找HTTP_X_REQUESTED_WITH,如果是XMLHttpRequest,那么将返回True,否则返回False。**一般在第三方库如jQuery中使用ajax方法都设置了这个值,如果自己手动写XMLHttpRequest,那么需要自己添加这个header,is_ajax这个方法才能生效
HttpResponse:
①、HttpResponse.__init__(content=’’,content_type=None,status=200,reason=None,charset=None)构造方法:
- content:代表要发送给客户端的内容。
- content_type:代表发送给客户端的内容类型,默认是“text/html;charset=utf-8”。
- charset:响应体的编码,如果没有指定,则会使用content_type中设置的charset。
②、response = HttpResponse()
response.set_cookie(key,value=’’,max_age=None,expires=None,path=’/’,domain=None,secure=None,httponly=False)
设置cookie的方法
- key:cookie的key
- value:cookie的value
- max_age:cookie最大的过期时间
- expires:cookie的过期时间和日期
- path:针对哪个目录下有效果
- domain:域名,如果你想跨域使用cookie,必须设置这个值,比如domain=”.lawrence.com”,那么www.lawrence.com和blogs.lawrence.com和calendars.lawrence.com都可以访问到这个cookie
- httponly:如果设置为True,客户端的js代码将不能访问到cookie
- delete_cookie(key,path=’/’,domain=None):删除cookie
django的表单:
django中的表单不是html中的那个表单.**这个表单是用来验证数据的合法性的一个东西**,也可以生成HTML代码
表单Form常用的方法和属性:
- is_valid(): 判断当前表单数据是否可用
- cleaned_data:如果is_valid()返回True,那么cleaned_data将会返回一个名叫cleaned_data的字典
创建注册函数:
def regist(request):