Django(入门终章)长达三万五千字的博文

Posted HUTEROX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django(入门终章)长达三万五千字的博文相关的知识,希望对你有一定的参考价值。

文章目录

前言

在此之前,你需要掌握

  1. html
  2. CSS
  3. JS
  4. JQuery
  5. Linux
  6. SQL
  7. Redis

python部分:

  1. 多线程,多进程,同步,线程池,队列,了解GIL
  2. socket 网络编程 TCP,UDP,HTTP

最好掌握部分:
正则表达式
xpath

这个终章其实是对前面的django系列做一个汇总,到时候你直接翻看这一篇博客就好了。目前涉及了django的基本操作,模型,中间件,等等,还有常见的一些错误的解决方案。

Django的安装

虚拟环境的配置

在使用django之前建议先设置虚拟环境,这样做的目的是为了让你的环境更加的干净。
具体如何去做,可以见我先前写的博客:博客链接
这个写的是使用virtualenv和virtualenvwapper去搭建一个虚拟环境。这个效果是你直接使用pycharm是一样的,上面都有介绍,在Linux下和在Windows下。
你要是直接在pycharm的话只需要鼠标点点就好了。当然这里补充一下如何直接使用virtualenv在window下面使用,这个在我上面的博客里面没有说到。

1.创建项目文件
2.使用指令 virtualenv env 创建虚拟环境(此时文件名为env)
3.找到Script目录
4.执行启动脚本(关闭时启动关闭脚本)


之后在你的IDE里面指定虚拟环境就好了。
直接用pycharm的话就比较友好了。

创建Django项目

Django项目的目录结构


他们之间的关系如下图:

创建项目
django-admin startproject projectname
创建应用
django-admin startapp appname

创建完之后进行应用注册,pycharm可能创建django项目的时候不会默认帮你创建一个应用项目所以还要控制台自己创建,此外,pycharm默认帮你创建好了虚拟环境。

项目文件关系图

首先来看看路由文件,这个文件是负责处理请求路径的。

当路由过来后,执行views的函数。注意我这里的时APP下的函数,函数放在views下

模板文件
我们读取的HTML文件就放在我们的模板文件当中。

之后时models文件,这个就是负责我们对数据库的处理部分。

多重路由

当我们的逻辑处理复杂时就需要使用到这个玩意了,我们一般在项目设置多重路由。
我们可以在应用当中创建路由文件。

这个其实和主路由文件很像。
然后我们去主路由文件声明。

那么当你访问 /Two/index这个目录时就会得到响应。

Django数据库的配置

激活默认sqllite

在Django当作默认带有一个数据库

接下来请使用pycharm的数据库工具,vscode请下载相关插件(目前我学习的环境还是windows等我做项目了将迁移到Ubuntu,写md文档是个好习惯,我会不断记录并上传到csdn)

找到箭头指向的位置,我的时2018专业版,如果是其他版本可能不在这个位置,找一下。


那么此时你的右侧就会出现表,但是还没完,你得迁移一下。
输入指令(控制台)

python manage.py migrate

如果一切顺利的话你就可以看到如下图:

之后你就可以点击表进行查看,更改等,非常方便。

切换数据库(sql)

在我们的settings可以搞定修改,但是这里还有几个问题。

        'ENGINE':'django.db.backends.mysql',
        'NAME':'数据库名',
        'USER':'username',
        'PASSSWORD':'password',
        'HOST':'host',
        'PORT':'port',

下载驱动安装,这里我们必然使用pymysql。但是在使用是注意一个问题,找到,初始化文件。
写下这个代码,进行驱动伪装,伪装成MYSQLDB

之后迁移,

python manage.py migrate

数据库简单操作

创建表

这个在我们的models处理。

现在我们创建了表,但是还要,完成映射,也就是把文件代码转一下

python manage.py makemigrations

然后会生成这样的文件

然后在迁移

python manage.py migrate

CURD简单操作

这个就直接演示流程了。

1. 找到表,也就是定义表的那个类,这里是Student类
2. 对实例对象操作(students = Student())
3. 增加 例如: students.name = ‘jack’,students.name = 'jack1’此时就会加入两个数据
4. 读取 students.object,all()读取所有 students.object.get(条件例如:pk=2找到id=2的)
5. 修改,基于查询,找到后直接修改 例如:stu1 = students.object.get(pk=2) stu1.name=‘hello’
6. 删除,基于查询,直接delete() stu1.delete()
7. 最后,所有的操作都必须提交
8. students.save()否则提交不了

补充

示图过程

--------------------------------------------------------------------------------------------------------------

表的创建

表的简单创建

要想创建表,那么就必须先继承Model,这个其实是由于Django自己的一个数据处理方式,在Django当中所有的数据库操作都做了封装。

from django.db import models


class Student(models.Model):
    S_name = models.CharField(max_length=32)
    S_age = models.ImageField(default=1)

此时我们已经创建好了一个表。
但是我们在处理时还需要进行操作。

python manage.py makemigrations
python manage.py migrate

至于这是什么操作,我们得先来了解一下django对数据模型的处理。

Django的创建流程

在此之前我们先来看看Django对数据库处理这块的大致模式。

所以我们发现django之所以能够对数据库的操作做出封装,其实就是有一个处理机制,这个机制相当于翻译器,能够帮助我们把我们的操作,变成对应数据库的操作语言。
因此要想实现这个方案,那么就存在一个转换过程,和实际到数据库的操作过程。
而这个就是我们刚刚的

python manage.py makemigrations
python manage.py migrate

当执行第一条指令时,它生成了这样一个文件,里面写了这样一些东西。(这个其实昨天的博客有提到)


之后执行第二条指令,那么我们的表就创建好了。


但是这里注意的是,他这个名字并不是Student而是他自己又生成了一个名字,存在数据库里面。

“个性化”表的创建

对表字段的控制

db_colum              字段名
null                  False表示字段不可为空
blank                 False表示字段不可为空白
primary_key           设置为主键(默认会给你生成一个主键字段id,就像上面展示的表一样)
unqiue   			  是否为唯一

示例:

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	p_age = modeIntegerField(default=18)
	p_sex  = models.BooleanField(default=False)

这里注意一下,对应sql而言其实,只有几个类型字符串,数字,日期这几种。那个Boolean其实在django中是使用短整型来做的。这一点可以去查看它所生成的DDL。

改表名

这个也简单,看代码

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	p_age = modeIntegerField(default=18)
	p_sex  = models.BooleanField(default=False)
	class Meta:
		db_table = "Person"

但是请你注意一点,那就是无论是对表名进行修改还是对字段进行修改,其实都是修改的数据库里面的内容,当我们用代码进行控制时,还是以我们自己定义的类名,变量名来进行的!!!!!!

表的赋值

属性赋值法

这些方法是我自己定义命名的可能不准确.
这个是直接实例对象然后赋值,之后save()保存,上传到数据库的.

def set_value():
	person = Person()
	person.p_age=20
	person.p_name = "XiaoMing"
	person.save()

实例赋值法

这个就是在new(创建一个对象的时候直接传值)

person = Person(p_name="XiaoMing",p_age=20)
缺点就是在编写代码的时候IDE没有提示,而且容易搞错,且有Django版本兼容问题

自定义类方法赋值

我们来创建一个create()方法,在Person中

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	p_age = modeIntegerField(default=18)
	p_sex  = models.BooleanField(default=False)#0女1男
	class Meta:
		db_table = "Person"
	@classmethod
	def create(cls,p_name,p_age=18,p_sex=True):
		return cls(p_name=p_name,p_age=p_age,p_sex=p_sex)
	

这个cls其实就是我们的Person类
调用创建

Person = Person.create("XiaoMing")
Person.save()

数据过滤器(查询)

这里的话先简单分两大类,一个是返回满足条件的查询结果,一个是返回不满足条件的结果。
此外又可以细分为,返回多个结果的方法和返回一个的方法。此外我们还需要明白一点那就是所以的查询其实是通过objects来控制的,而这个其实是一个控制器,我们是可以自己指定的。

返回多结果的方法

all()		返回所有结果
filter()    返回满足条件的所有结果
exinclude() 返回不满足条件的所有结果
order_by()  排序order_by('p_age') 按照年龄排序
values()	这个可以对返回的结果包装成一个列表,每一个元素是一个字典({’字段名':value})适合转为json

返回单个的方法

get()
first()
last()
count()		统计个数
exisits()	返回布尔值

这些所有的方法都是可以连用的

查询示例

def get_age(request):
	person = Person.objects.all().first()
	print(person.name)

这个是一个简单的查询,后面还可以接很多的过滤…
例如我要查询年龄在大于18小于80的我们可以这样写

persons = Person.objects.filter(p_age>18).filter(p_age<80)

也可以这样写.

persons = Person.objects.filter(p_age__gt=18).filter(p_age__lt=80)

变量名__条件 = 值
这样的形式来
那么条件大概有
gt >
lt <
gte >=
lte <=
exact =
in 在什么中:Person.objects.filter(p_age__in=[18,20,30])

contains : 包含类似于sql中的like like %xx%(icontains忽略大小写)
startswith :以什么开头(istartswith)
endswith :什么结尾(iendswith)

现在我查询名字当中有"X"的

persons = Person.objects.filter(p_name__contains="X")
for person in persons:
	print(person.p_name)
	

那么现在我们通过这个来简单的去实现一下我们的人事验证,我们假设名字是用户名,年龄是密码,看看这个人是不是这个人.

def find_person(person_name,person_age):
	persons = Person.objects.filter(p_name=person_name)
	if person.exists():#person.count()
		person = persons.first()
		if person.p_age == person_age:
			print("信息无误")
		else:
			print("年龄错误")
	else:
		print("查无此人")
		
	
	

查询切片

还是先前的例子.

persons = Person.objects.filter(p_age>18).filter(p_age<80)

这个家伙返回的是一个可迭代对象,那么就意味着可以进行切片.
但是这个切片的原理其实是类似于sql当中的limit offerset操作的.并不是直接把全部结果加载到内存当中,然后进行切片操作的.

persons = Person.objects.filter(p_age>18).filter(p_age<80)[0:3]
左闭右开
[0,3)

此外就是切片当中不能有复数原因就是那玩意是limit操作

跨关系查询

这个其实说白了就是表的关联.
现在假设创建两个表,一个是学生表,一个是班级表,关系为多对一。

class Grade(models.Model):
	g_name = models.CharField(max_length=32)
	

class Student(models.Model):
	s_name = models.CharField(max_length=16)
	s_grade = models.ForeignKey(Grade) #添加外键约束
	

这里的话其实有两个方法,假设我们查询有个叫 小明 的学生的班级是什么.
第一个分开来一步步查询.我们先假设名字是唯一的

student = Student.objects.get(s_name="小明")
grade_name = student.s_grade.g_name

一次性查询,一步到位,我们直接查班级

grade_name = Grade.objects.filter(student__s_name="小明").first().g_name

F 对象

这个其实是和查询过滤有关的,在Django.db.models下,这个主要是可以帮助我们对两个字段进行比较.
例如:

class Company(models.Model):
	c_name = xxxxx
	c_girl = xxxxx 男孩人数
	c_boy = xxxxxx 女孩人数

现在我要把男孩比女孩多的公司找出来

companies = Company.objects.filter(c_boy>F('c_girl'))
或者
companies = Company.objects.filter(c_boy__gt=F('c_girl'))

Q对象

这个主要是帮助我们多个条件过滤用的.好处就是不用写那么多过滤方法了.
例如:

persons = Person.objects.filter(p_age>18).filter(p_age<80)

可以改成这样

persons = Person.objects.filter(Q(p_age>18) and Q(p_age<80))
此外还可以这样
persons = Person.objects.filter(Q(p_age>18) & Q(p_age<80))

or  ---> |
not ---> ~

聚合函数

举个例子找我们先前定义的Person我们找年纪最大的怎么找

max_person = Person.objects.aggregate(Max("p_age"))
Max也在 django.db.models下
此外还有:
	Max
	Avg
	Min
	Sum
	Count
	返回结果如下格式:
	例如:{'c_age_max':88}

这个其实是做了封装.

模型成员

在前面不知道你注意到了没有,每次我要查询数据都需要调用objects那么这玩意到底为何物嘞.这个其实就是一个模型.

但是这里分为两种,一种是隐性的一种是显性的.我们的objects就是隐性的,最明显的原因就是,我们压根就没有定义这玩意.这个是我们父类Model自带的.那么显性又是怎么样子的呢,显然我们自己定义的就是显性的.那么这样做的好处是什么呢,那就是我们可以自己制定一个规则.
下面举个简单的例子.

显性模型

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	is_delete = models.BooleanField(default=False)#0没有1已删除

假设我们要拿到数据拿到的数据必然是没有删除的.那么常规下我们可以这样写

persons = Person.objects.filter(is_delete=False)

但是显然我们每次拿数据的时候都需要过滤一下,这个那么如果每次都这样写的话就会显得很麻烦,所以我们可以这样自己指定一下模型,写个过滤规则.

class PersonManager(model.Manager):
	def get_queryset(self):#这个是模型返回的数据的方法
		return super(PersonManager,self).get_queryset().filter(is_delete=False)

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	is_delete = models.BooleanField(default=False)#0没有1已删除
	objects = PersonManager()#你叫其他名字也可以到时候这样例如:p_m,那么调用就是:Person.p_m.all()等
	
	

下图是Model.Manger的部分代码

软删除

都说到这里了,就不得不说一下软删除这玩意,一个数据尤其是重要数据例如用户数据是不可能说删除就删除的,那么这个时候的删除并不会在数据库中真正删除,而是可以通过我们刚刚那个类似于is_delete的字段的值来进行适当的隐藏,过滤.也就是说在删除的时候我们只是设置那个值为真,并且我们自己指定了模型所以为真的就会先被过滤,那么一来数据就实现了一种删除效果.
怎么做呢,也很简单,重写delete方法即可.

class Person(models.Mode):
	p_name = models.CharField(max_length=16,unqiue=True,null=False)
	is_delete = models.BooleanField(default=False)#0没有1已删除
	objects = PersonManager()#你叫其他名字也可以到时候这样例如:p_m,那么调用就是:Person.p_m.all()等
	def delete(self):
		self.is_delete = True
		self.save()	

这样一来就好了.

补充(Django数据库时区域问题)

由于在Django当中自己使用了一个时区(我们自己设置的,默认也是世界时间)
这个三个解决方案,一个是设置数据库的时区.
还有一个就是将错就错暂时不去生效时区设置

最后一个是校验时区,把我们当前的时区改为世界时区.
参考博客:django—时区问题(USE_TZ)

--------------------------------------------------------------------------------------------------------------

模板语句

模板是存在于HTML代码当中的,但是这个是不会被浏览器识别的是需要Django或者其他的框架或者渲染器渲染后,才会在浏览器当中显示的。在这里模板可以大致分为两种使用,一种是模板逻辑语句,例如条件判断,循环。另一种是赋值,这个通过强大的‘点’语法轻松搞定。

这里简单说一下django当中的执行流程。我们在使用时是了render直接把模板和数据给了出去。
事实上完整的步骤是先加载,然后渲染,然后使用httpResponse发送。(更新随缘,内容整理起来比较费劲)

temp = loder.get_template("Base.html")
content = temp.render(data)
return HttpResponse(temp)

插值

点 语法

在模板当中的点语法很有意思,它类似于python当中的点语法,点万物。
下面是一个示例:

通过key拿值

def Test(request):
	Data = {
		"name":"xiaoming",
		"age":18,
		"Person":{"height":175},
		}
	return render(request,"base.html",content=Data)

现在拿到Data的名字

<p> {{name}} </p>

拿到Person身高

<p> {{Person.height}} </p>

通过属性&方法

此外点语法还可以调用方法。
举个例子:

class Student(models.Model):
    S_name = models.CharField(max_length=32)
    S_age = models.ImageField(default=1)
    def get_s_name(self):
    	return self.S_name
def Test(request):
	student = Student.objects.get(S_name="XiaoMing")
	Data = {
		"name":"xiaoming",
		"age":18,
		"Person":{"height":175},
		"student":studnet,
		}
	

以上是关于Django(入门终章)长达三万五千字的博文的主要内容,如果未能解决你的问题,请参考以下文章

Python从入门到精通五万六千字对Python基础知识做一个了结吧!(二十八)值得收藏

Python从入门到精通五万六千字对Python基础知识做一个了结吧!(二十八)值得收藏

两万五千字!写给设计师的数据可视化指南

一万五千字详解HTTP协议

c++之引用(五千字长文详解!)

五千字JVM调优参数记录