浏览器与服务器之间遵循的一个协议: HTTP协议
服务器与应用程序框架之间:wsgi
1.1 Django的简介
Django是一个重量型框架
主要目的:简便快捷开发
Django基于MVC模式,但是它是MVT模式的
MVC设计的框架
(1)重量级框架
(2)MVT模式
MVC :
定义:
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
2、创建项目的环境
虚拟环境:
项目所需要的第三方软件环境相互隔离
安装虚拟环境
sudo pip3 install virtualenv
sudo pip3 install virtualenvwrapper
创建虚拟环境
mkvirtualenv dj_3 -p python
切换虚拟环境
workon dj_3
删除虚拟环境
rmvirtualenv dj_3
退出环境
deactivate
3、安装Django,初步讲解
3.1安装Django:
pip install django==安装的版本号
一般安装在虚拟环境中
3.2创建项目:
django-admin startproject 项目名称
里面有一个和项目同名的文件夹,内部包含的是项目的配置文件
settings.py项目的整体配置文件
urls.py项目的URL配置文件
wsgi.py是项目与服务器的入口
manage.py是项目运行的入口
3.3 运行服务器
python manage.py runserver
注意点:如果不指定端口,默认是8000
python manage.py runserver 5000
3.5 创建模块
python manage.py startapp 模块名
user子模块
admin.py 后台管理站点的配置
apps.py 当前子应用的信息
models.py 保存书写的数据库模型
text.py 用来保存开发测试用例的,进行单元测试
views.py 书写逻辑,用来保存视图。
3.6 创建模块之后,注册子模块,注册到同名文件夹的setting中
pai0805中的settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"user.apps.UserConfig"
]
3.7 简单体验数据库交互
3.7.1 定义表与字段
一张表对应了一个类
user中models.py
class UserInfo(models.Model):
name = models.CharField(max_length=10)
age = models.IntegerField()
phone = models.CharField(max_length=11)
def __str__(self):
return self.name
类名对应的是表名
属性名对应的是字段名
注意点:继承于Model
3.7.2 迁移数据库表
1、生成迁移文件
python manage.py makemigration
2、执行迁移文件
pyhton manage.py migrate
迁移成功并且执行迁移之后,才真正在数据库产生表
3.7.3 创建超级权限账号和修改界面语言
pai0805中的settings.py
LANGUAGE_CODE = "zh-Hans"
TIME_ZONE = "Asia/Shanghai"
python manage.py createsuperuser
3.7.4 数据库的配置
1、设置数据库
pai0805中的settings.py
DATABASES={
"default":{
"ENGINE":"django.db.backends.mysql",#这个参数是设置数据库
"NAME":"数据库名字",#使用的数据的名字
"USER":"root",#数据库的用户名
"PASSWORD":"mysql",
"HOST":"127.0.0.1",#数据库主机的地址
"PORT":3307,#数据库的端口
}
}
2、添加驱动
pai0805中的 __init__.py
import pymysql
pymysql.install_as_MySQLdb()
3、在admin站点管理中注册models
user 中 admin.py
from django.contrib import admin
from user.models import UserInfo #导入
admin.site.register(UserInfo)
3.7.5 查看
use pai0805;
show tables;
其中user_userinfo表是创建的
3.8 实现网站的用户信息展示
3.8.1 定义视图,处理业务
user中view.py
视图的作业:创建业务逻辑,完成路径--视图的匹配,返回给对应路径的数据或者网页
视图函数
def userinfo():
"""这个视图函数实现的是暂时用户的信息,匹配的路径/userinfo"""
pass
def index(request):
print("----------------------")
print(type(request))
print(request)
# return "hello world"
return HttpResponse("hello world")
Request是一个请求对象,可以是别的名字,但是一般是request,每一个视图函数都必须要有一个参数来承接
视图函数,至少需要一个参数来接收Django传递过来的参数
3.8.2 配置路由URL
1、路由配置第一种方法:
from user import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r"^index/$",views.indesx),
]
2、第二种方法(分模块再集中)
(1)在项目所在的同名文件夹的urls里面配置include()将各个模块的URL加载
(2)在各个模块的URL里面进行配置URL-----VIEWS
(3)项目同名的urls值完成路由的分发匹配过程
真正匹配路径在各个模块的URL下面
视图与路径的匹配
同名文件夹中的urls.py中
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r"^book/",include("book.urls")),
url(r"^user/",include("user.urls")),
url(r"^username/",include("username.urls")),
]
各个子模块的urls.py中
from django.conf.urls import url
from username import views
urlpatterns = [
url(r"(?Pcity)/(?P\w+)/",views.username),
url(r"^huoqu/",views.huoqu),
url(r"^search/$",views.search),
url(r"^data/$",views.data),
]
3.9 配置html模板文件
3.9.1 创建一个名字叫templates的文件夹
3.9.2 配置文件夹的查找路径
在同名文件夹中settings.py中的
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',
],
},
},
]
3.9.3 返回模板到前端
def show(request):
# #创建连接
# con = pymysql.connect(host="localhost", user="root", password="535897", database="pai0805_2", port=3307,charset="utf8")
# #获取光标对象,操作句柄
# cur=con.cursor()
# #写查询语句
# sql1="select * from user_userinfo;"
# #进行查询
# ret_num1 =cur.execute(sql1)
# ret = cur.fetchall()
# return HttpResponse(ret)
from user.models import UserInfo
data = UserInfo.objects.all()
for i in data:
print(i)
#可以在info.html中设置界面的字体,格式
return render(request,"info.html",{"data":data[0],"data1":data[1]})
4.1 数据的查询
4.1.1 查询所有的数据
from user.models import UserInfo
data = UserInfo.objects.all()
格式: 模型类名.objects.all()
查询多条数据
4.1.2 按照指定条件查询
def get(self,*args,**kwargs):
注意点:
1、get()获取的是指定条件符合数据,只有一条
4.1.3 计数语句
data = Userinfo.objects.count()
返回的是数据的条数
4.1.4 符合条件的多条数据查询
1、比较查询
符合条件的多条语句
1、比较查询 大于 gt greater then
data = UserInfo.objects.filter(id_gt = 1)
id大于等于3 gte
data = UserInfo.objects.filter(id_gte = 3)
id小于1的人
data = UserInfo.objects.filter(id_lt=1)
id小于等于1的人
data = UserInfo.objects.filter(id_lte=1)
注意点:
filter既可以查询一条语句,也可以查询多条语句
但是查询的结果放在一个列表里面、
如果查询不到任何满足条件的数据,则返回的是一个空列表
2、模糊查询
查找名字中带有王的人
data = UserInfo.objects.filter(name_contains = "王")
查找姓王的人
data = UserInfo.objects.filter(name_startswith = "王")
4.1.5 关于外键的查询
book_obj = BookInfo.objects.filter(personinfo__name__exact="猴子")
print(book_obj)
per_obj = PersonInfo.objects.filter(book__seltcount__gt=0)
print(per_obj)
注意点
#关联模型类的小写--属性名--条件筛选运算符=值
4.1.6 F()、Q()
#F()解决属性与属性的对比
#Q()表示逻辑关系
# ret1 = BookInfo.objects.filter(count__gt=F("seltcount"))
# print(ret1)
ret2 = BookInfo.objects.filter(seltcount__exact=F("count")*2,seltcount__gt=0)
print(ret2)
ret3 = BookInfo.objects.filter(seltcount__exact=F("count") * 2).filter(seltcount__gt=0)
print(ret3)
# ret4 = BookInfo.objects.filter(seltcount__exact=F("count") * 2, seltcount__gt~Q)
# print(ret4)
ret5 = BookInfo.objects.filter(Q(seltcount__exact=0)&Q(seltcount__exact=5))
print(ret5)
注意点:
F()对象是用来表示两个属性之间的对比
Q()对象用来表示各个关系的与或非的操作,& | ~
4.2 数据的增加
4.2.1 第一种方式
通过创建对象,进行属性设置,最后再保存的方式
book1 = BookInfo(booknane="红楼梦",time="1700-1-1")
book1.save()
4.2.2 第二种方式(重点)
PersonInfo.objects.create(name="猴子",weapon="棒子",book=book1[0])
4.3 当数据表存在数据的时候,对于修改数据表
第一种
book2 = BookInfo.objects.get(pk=3)
book2.time="1973-1-1"
book2.save()
第二种
BookInfo.objects.filter(name="三国演绎").update(time="1973-10-01")
4.4关于数据库表名的设计
如果没有指定数据库的表名,则MYSQL中会以应用名_模型类名的小写作为数据库的表名
设计数据库表名:
在模型类的内部进行表的设计
class PersonInfo(models.Model):
gender_choice = (
(0,"boy"),
(1,"girl"),
)
#名字
name = models.CharField(max_length=30,verbose_name="人物名字")
# 性别
gender = models.SmallIntegerField(choices=gender_choice,default=0,verbose_name="性别")
# 武器与技能
weapon = models.CharField(max_length=300, verbose_name="武器")
# 逻辑删除
is_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
book = models.ForeignKey(BookInfo,on_delete=models.DO_NOTHING,verbose_name="外间图书")
def __str__(self):
return self.name
class Meta:
db_table = "personinfo"
#指定数据库的表名
verbose_name = "人物信息"
#修改后台管理中心中数据库表的名字
verbose_name_plural=verbose_name
#将复数形式去除
注意点:
修改数据库的表名需要迁移
4.5 关于模型与数据库数据的关系
from book.models import BookInfo,PersonInfo#测试的时候,需要将使用到的模型导入
add = BookInfo(name="书名",time="出版")#数据库的一条数据,其实就是模型类的一个实例
add.save()#保存,不保存不生效
当存在外键的时候:
person1 = PersonInfo()
person1.name="名字"
person1.book = add
person1.save()
Addinfo这个属性是一个外键,赋值的时候需要以对象进行赋值
约束
primary_key = False 主键
null = False 允许为空,默认为false,数据库的角度来说的
blank = False 字段允许为空白,表单验证
db_column = None字段的名称,没有指定的话,使用属性的名字
db_index=Flase给该字段设置索引
unique =Flase 说明该字段在这个表里面具有唯一性
delfault = 设置默认值
4.7 模型的相关字段
name = models.CharField(db_column="username",max_length=20)
phone = models.CharField(max_length=11,unique=True)
pwd = models.CharField(max_length=8,default="123")
pwd= mdoels.IntegerField(default="123")
models.AutoField()如果不指定,则自动指定属性名为id的自增长属性,一般不指定
models.BooleanField()布尔值
models.NullBolleanField()布尔值加null
models.TextField()大文本字段,字符在4000向上
models.DecimalField(max_digits=总位数,decimal_places=小数位数)#十进制浮点型
models.DateField()表示的是日期
models.TimeField()表示的是时间
models.DateTimeField()表示的是日期加时间
models.FileField()上传文件的字段
models.ImageField()对上传的文件进行校验,保证是有效图片
5、视图与模型的结合使用
以简单的用户注册为例
5.1 设计展示用户操作页面
注意点:视图函数至少有一个参数
必有要有响应对象返回
return HttpResponse("ok")
5.3 HTTP请求对象
def index(request):
print(request)
return HttpResponse("123")
注意点:
1、这是一个HTTP请求对象
2、这个请求对象里面封装的是请求信息,包括请求的方式,数据等
5.3.1 request.body
当非表单数据,request.body 来获取到请求体数据,但是,body获取的数据是bytes类型
def index(request):
print(request.body)
return HttpResponse("123")
一般情况下,都是json
5.3.2 request.GET
获取到的都是类字典类型
5.3.3 request.POST
获取到的都是类字典类型
5.3.4 request.META获取请求头的数据
def index(request):
print(request.META)
requset.META这个属性,用来获取的是请求头header部分所有的数据
他是一个字典类型
5.4 httpresponse对象
5.4.1 render函数的具体使用
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Returns 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)
注意点:
1、 Render函数适用的范围是:有网页,有填充网页的数据
2、 Render这个函数的第一个参数是当前路径的请求对象
3、 Context这个参数指向的是填充网页的数据,注意它的格式必须是字典
5.4.2 HTTPresponse
def __init__(self, content_type=None, status=None, reason=None, charset=None):
# _headers is a mapping of the lower-case name to the original case of
# the header (required for working with legacy systems) and the header
# value. Both the name of the header and its value are ASCII strings.
self._headers = {}
self._closable_objects = []
# This parameter is set by the handler. It's necessary to preserve the
# historical behavior of request_finished.
self._handler_class = None
self.cookies = SimpleCookie()
self.closed = False
if status is not None:
try:
self.status_code = int(status)
except (ValueError, TypeError):
raise TypeError('HTTP status code must be an integer.')
if not 100 <= self.status_code <= 599:
raise ValueError('HTTP status code must be an integer from 100 to 599.')
self._reason_phrase = reason
self._charset = charset
if content_type is None:
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
self.charset)
self['Content-Type'] = content_type
注意点:
1、适用范围,返回的是让浏览器或者客户端展示的字符串
5.5 csrf的问题
5.5.1 在表单中增加
5.6 关于路径匹配的补充知识
5.6.1 路径匹配
url(r"^userna(\w+)/",views.username),
url(r"^huoqu/",views.huoqu),
Exception Value:
username() takes 1 positional argument but 2 were given
URL函数正则匹配,如果需要匹配组,则匹配出来的组信息,会自动传递给对应的视图函数
url(r"^userna(\w+)/"[0],views.username),
5.6.2 关键字参数
urlpatterns = [
url(r"(?Pcity)/(?P\w+)/",views.username),
url(r"^huoqu/",views.huoqu),
url(r"^search/$",views.search),
url(r"^data/$",views.data),
]
def username(request,city,cname):
# #创建连接
# con = pymysql.connect(host="localhost", user="root", password="535897", database="pai0805_2", port=3307,charset="utf8")
# #获取光标对象,操作句柄
# cur=con.cursor()
# #写查询语句
# sql1="select * from user_userinfo;"
# #进行查询
# ret_num1 =cur.execute(sql1)
# ret = cur.fetchall()
# return HttpResponse(ret)
print(city)
print(cname)
return render(request,"register.html")
注意点:?P
5.7 查询对象的获取
try:
book = BookInfo.objects.get(name="三国演绎")
except Exception as e:
print(e)
#通过书籍查找该书籍查找该书籍中的人物
print(book)
peo = book.personinfo_set.all()
print(peo)
obj = PersonInfo.objects.get(name="猴子")
print(obj.book.id)
print(type(obj.book))
#关联过滤查询
book_obj = BookInfo.objects.filter(personinfo__name__exact="猴子")
print(book_obj)
#关联模型类的小写--属性名--条件筛选运算符=值
per_obj = PersonInfo.objects.filter(book__seltcount__gt=0)
print(per_obj)
注意点:
1、request。GET\POST 获取的都是QUERYDICT对象
2、获取QueryDict的某一个值对应的对象,使用的是get ,但是如果一个键名对应多个值的时候,get只能获取一个,并且是最后一个
3、如果想要获取多个值,需要使用的是getlist
4、get \getlist 都可以设置默认值,当获取不到数据的时候(当键名不存在获取或者getlist获取到空列表的时候)
5.8 form表单的提取
注意点:
当name值相同的时候,可以设置value的值
5.9 关于浏览器与服务器之间的状态保持
浏览器与服务器之间是无状态的
Ssession:存在服务器一端
Cookie:存在浏览器一端
关系:一一对应的
5.9.1 cookie
特点:
1、键值结构
2、cookie是基于域名安全的,不同域名之间cookie是不可以进行相互的访问的
3、当浏览器请求某一个网站,会将与当前网站所有的cookie提交给服务器
4、cookie数据不允许存储敏感信息,密码,支付宝密码
创建cookie
Response.set_cookie()
删除cookie
Resposne.delete_cookie()
读取cookie
Request.COOKIES.get(键名)
Cookie虽然存储在浏览器一端,但是,它是在服务器一端进行设置的,
5.9.2 session
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
1、如果需要使用数据库存储session,安装应用
'django.contrib.sessions',
2、在数据库中
注意点:在Django项目中,session的引擎没有设置,因为则是默认的存储方式