Django
安装
直接使用命令安装
pip install Django
conda install Django
#这样输命令会直接安装当前最新版
#需要较低版本的话,可以在后面加入版本号
pip install Django==2.1
conda install Django==2.15
建立项目
#创建一个项目,XXX是你建立的项目文件夹名
django-admin startproject XXX
#然后可以进入项目文件夹,运行一下,测试环境是否可用
python manage.py runserver
python manage.py runserver 8000(端口号)
#建立一个新的app,XXX表示app名字
python manage.py startapp XXX
#建立app之后需要将app名添加到setting.py中INSTALLED_APPS中
APP使用
app的使用主要是修改appName/views.py和projectName/urls两个文件
定义视图函数
通过编写不同的函数来实现不同的功能,函数第一个参数是request请求,后面的参数可以在url.py
文件中使用,return返回render函数,第一个参数依然是request,后面是返回的页面。
页面存储的位置是appName/templates/XXX,前端文件的位置是固定的。文件夹templates是自己创建的。
'''
定义视图函数
'''
def test(req):
return render(req,"test.html")
def page(req,pagename):
return render(req,pagename)
def login(req):
username = req.GET.get("username",None)
password = req.GET.get("password",None)
if username == "test" and password == "test":
print("success!")
return render(req,"test.html")
else:
return render(req,"login.html")
绑定链接地址
链接地址就是你访问时的url地址,可以使用变量,但是格式是固定的,<str:pagename>
注意需要使用import,将app文件引入
from myapp import views as myviews
urlpatterns = [
path('admin/', admin.site.urls),
path('test/',myviews.test),
path('page/<str:pagename>',myviews.page),
path('login/',myviews.login),
]
请求方式
get
get请求接受参数不用多余的设置,默认就是可以的
username = req.GET.get("username",None)
password = req.GET.get("password",None)
post
post一般需要一些设置,根据版本不同,设置也不太一样
首先需要设置setting.py 中 APPEND_SLASH=False
,如何没有的话需要加上这一句。
另外在请求是需要加上跨域请求。
<form action="/login/" method="post">
{% csrf_token %} #必须加上这一句
login:
<input type="text" id="username" name="username" /> <br>
password:
<input type="password" name="password" /> <br>
<input type="submit" value="login"/>
</form>
接受参数基本和get相同
username = req.POST.get("username",None)
password = req.POST.get("password",None)
响应重定向
响应重定向使用需要引入相应的库文件,redirect中写的是一个URL,而render中参数是req,和templates中的文件。
from django.shortcuts import render,redirect
def testredirect(req):
return redirect("http://baidu.com")
传递参数时可以采用?name=XXX&pass=XXX
这种形式
数据传递
#接受来自前端的数据,分为get和post两种方法
def login(req):
# username = req.GET.get("username",None)
# password = req.GET.get("password",None)
username = req.POST.get("username",None)
password = req.POST.get("password",None)
if username == "test" and password == "test":
print("success!")
return render(req,"test.html")
else:
return render(req,"login.html")
#向前端界面传递参数
def testdata(req):
context = dict()
context["name"] = "user"
context["pass"] = "pass"
return render(req,"testdata.html",context=context)
#前端接受,采用{{XX}}的方式
{{name}}
{{pass}}
session
session的使用依赖表,所以使用的话需要建立一个表
python manage.py makemigration #如何已经存在表,则先使用该命令更新
python manage.py migrate #没有的话可以直接执行这个,建立表
使用session需要的步骤
#添加表,用来支持session
python manage.py migrate
#添加session
def login(req):
username = req.POST.get("username",None)
password = req.POST.get("password",None)
if username == "test" and password == "test":
req.session['name'] = username #session对象中存储数据
print("success!")
return render(req,"test.html")
else:
return render(req,"login.html")
#前端获得session
{{request.session.name}}
#在后端获得session
request.session.get("name")
在setting.py中可以修改相应的参数(直接添加到setting)
SESSION_COOKIE_AGE=60*30 #30分钟
SESSION_EXPIRE_AT_BROWSER_CLOSE=TRUE #浏览器关闭时session失效
模板
### for标签
#列表、集合、元组的循环
{% for us in info %}
{{us}}
{% endfor %}
#字典的循环
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
##当列表中可能为空值时用 for empty
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表为空</li>
{% endfor %}
### 注释
{# 注释 #}
###if标签
{% if var >= 90 %}
成绩优秀,自强学堂你没少去吧!学得不错
{% elif var >= 80 %}
成绩良好
{% elif var >= 70 %}
成绩一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格啊,大哥!多去自强学堂学习啊!
{% endif %}
model
使用
model是用来使用数据库的,要使用需要以下几个步骤
一、首先需要我们下载安装数据库,安装数据库相关模块,可以使用命令
pip3 install pymysql
pip3 install mysqlclient
二,需要在setting文件中配置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'PORT':3306,
'HOST':'127.0.0.1',
'USER':'ROOT',
'PASSWORD':'pass',
'NAME': 'dhango',
}
}
三、需要我们写模型对象
from django.db import models
# Create your models here.
#定义模型对象
class Userinfo(models.Model):
userid = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=50,unique=True)
password = models.CharField(max_length=30)
class Meta:
db_table = 'userinfo'
class orderinfo(models.Model):
orderID = models.BigIntegerField(primary_key=True)
orderData = models.DateField(auto_now=True) #添加数据时,时间默认为系统当前时间
orderMon = models.FloatField()
Userinfo = models.ForeignKey(Userinfo,on_delete=models.CASCADE) #设置外键关联
class Meta:
db_table = 'orderinfo'
四、创建注册模型对象
python3 manage.py makemigrations
五、创建表
python3 manage.py migrate
创建好之后就应该是这样的
常用参数
1、CharField:字符串类型,映射到数据库中会转换成varchar类型,使用时必须传入max_length属性以定义该字符串的最大长度,如果超过254个字符,就不建议使用CharField了,此时建议使用TextField。
2、EmailField:在数据库底层也是一个varchar类型,默认最大长度是254个字符,当然也可以自己传递max_length参数,这个Field在数据库层面不会限制一定要传递符合email条件的字符串,只是以后在使用ModelForm表单验证时,会起作用
3、URLField:类似于CharField,在数据库底层也是一个varchar类型,只不过只能用来存储url格式的字符串。并且默认的max_length是200,同EmailField
4、FloatField:浮点数类型,映射到数据库中会变成double类型
5、IntegerField:整数类型,映射到数据库中会变成11位的int类型
6、BigIntegerField:大整形。值的区间是-9223372036854775808——9223372036854775807
7、PositiveIntegerField:正整形。值的区间是0——2147483647
8、SmallIntegerField:小整形。值的区间是-32768——32767
9、PositiveSmallIntegerField:正小整形。值的区间是0——32767
10、BooleanField:布尔类型(True/False),映射到数据库中会变成长度只有1位的tinyint类型,这个Field不接受null参数,要想使用可以为null的布尔类型的字段,就要使用NullBooleanField
11、AutoField:自增长类型,映射到数据库中是11位的整数,使用此字段时,必须传递primary_key=True,否则在生成迁移脚本文件时,就会报错,一个模型不能有两个自增长字段。一般情况下我们用不到这个字段,如果不定义主键,django会自动的为我们生成id字段作为主键
12、BigAutoField:自增长类型,用法同AutoField。映射到数据库中会成为20位的bigint类型
13、DateTimeField:日期时间类型,在python中对应的是datetime.datetime类型,在映射到数据库中也是datetime类型。使用这个Field可以传递以下几个参数:
auto_now=True:在每次这个数据保存的时候,都使用当前的时间。比如作为一个记录修改日期的字段
auto_now_add=True:在每条数据第一次被添加进去的时候,都使用当前的时间。比如作为一个记录第一次入库的字段
注意:如果在setting.py中配置了USE_TZ=True,那么上两个默认值都来自于django.utils.timezone.now所转化来的值在模板中将一个UTC时间转换成本地时间:
首先模板HTML文件的开头导入tz:
{% load tz %}
在传递过来的时间变量utc_time中使用localtime过滤器:
{{utc_time | localtime}}
其实,django知道我们的想法,已经为我们做好了配置,我们并不需要配置其他的东西就可以直接使用{{utc_time}},此时只要我们在setting.py文件中设置 USE_TZ=True,TIME_ZONE='Asia/Shanghai',UTC时间变量在渲染到模板上的时候会自动的为我们加载成TIME_ZONE中所设置的时区的时间。14、DateField:日期类型,用法同DateTimeField,在python中对应的是datetime.date类型,在映射到数据库中是date类型
15、TimeField:时间类型,用法同DateTimeField,在python中对应的是datetime.time类型,在映射到数据库中是time类型
16、FileField:用来存储文件的
17、ImageField:用来存储图片文件的
18、TextField:大量的文本类型
19、
**DecimalField**: 一个固定精度的十进制数类型,使用时必须要传递两个参数,max_digits数字的最大总长度(不含小数点),decimal_places小数部分的长度
Field的常用参数:
1、null:标识是否可以为空,默认是为False。在使用字符串相关的Field(CharField/TextField/URLField/EmailField)的时候,官方推荐尽量不要使用这个参数,也就是保持默认值False。因为Django在处理字符串相关的Field的时候,即使这个Field的null=False,如果你没有给这个Field传递任何值,那么Django也会使用一个空的字符串""来作为默认值存储进去。因此如果再使用null=True,Django会产生两种空值的情形(NULL或者空字符串)。如果想要在表单验证的时候允许这个字符串为空,那么建议使用blank=True。如果你的Field是BooleanField,由于BooleanField不接受null参数,因此你如果想要设置这个字段可以为空的bool类型,那么对应的可空的bool类型字段则为NullBooleanField。2、blank:标识这个字段在表单验证的时候是否可以为空,默认是False。这个和null是有区别的,null是一个纯数据库级别的。而blank是表单验证级别的。
3、db_column:这个字段在数据库中的名字。如果没有设置这个参数,那么将会使用模型中属性的名字。
4、db_index:标识这个字段是否为索引字段。
5、default:默认值。可以为一个值,或者是一个函数,但是不支持lambda表达式。并且不支持列表/字典/集合等可变的数据结构。在用函数作为值传递给default时,只能传递函数名,不需要加括号。
6、primary_key:是否为主键,与AutoField/BigAutoField连用,默认是False。
7、unique:在表中这个字段的值是否唯一,在数据库中就是唯一约束,一般是设置手机号码/邮箱等。
8、choices:在一个范围内选择出一项,注意这个选项与ForeignKey的区别
作用:1、django admin中显示下拉框;2、避免连表查询TYPE_CHOICES = ( #数据库只保存内部元祖的第一个值,后面的值保存在内存中
(0, '---'),
(1, '第一类'),
(2, '第二类'),
(3, '第三类'),
)
type = models.IntegerField(default=0,choices=TYPE_CHOICES)
数据库操作
创建项目
django-admin startproject django_model
创建应用
python manage.py startapp model
- 配置应用 model, 编辑 django_model/settings.py 文件:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'model',
]
- 配置Mysql数据库:编辑 django_model/settings.py 文件, 内容如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # mysql数据库引擎
'NAME': 'my_model', # 数据库名字
'USER': 'root', # 用户名
'PASSWORD': 'fe_cow', # 密码
'HOST': 'localhost', # 主机
'PORT': '3306' # 端口
}
}
-
创建应用所需数据库表, 首先我们创建数据库:
create dababase my_model charset = utf8;
-
注意: 使用PyMysql数据库驱动,需要在 djangomodel/init_.py 中增加如下代码:(python2不需要配置这项)
import pymysql
pymysql.install_as_MySQLdb()
定义模型
- 定义模型其实就是定义一个python类;一个
模型类
代表数据库中一张表
,一个模型类的实例
代表这个数据库表中的一条特定的记录
from django.db import models
class Publisher(models.Model):
"""出版社"""
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
country = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Author(models.Model):
"""作家"""
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
"""书"""
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author) # 书和作者是多对多的关系
publisher = models.ForeignKey(Publisher) # 书和出版者是多对一的关系
publication_date = models.DateField()
def __unicode__(self):
return self.title
-
定义完模型后,要执行数据库迁移操作:
先执行
python manage.py makemigrations
在执行:python manage.py migrate
-
一张表中定义了多对多的关系,ORM会自动创建实现多对多关系的第三张表。
数据库的操作
- 通过python shell 来演示数据库的操作。在终端切换到项目根目录下,输入命令
python manage.py shell
进入shell操作环境。
增删改查
1 创建记录
方法一:实例化(调用save()方法
之前,Django不会访问数据库;save()方法
没有返回值)
>>> from apps.models import Author
>>> author = Author(last_name='fe_cow')
>>> author.save()
>>> print author
fe_cow
方法二:create() (只用一条语句创建并保存一个对象,使用create()方法
。)
>>> Author.objects.create(first_name='fe',last_name='cow', email='280773872@qq.com')
方法三:get_or_create()
, 这种方法可以防止重复
(速度稍慢,因为会先查数据库), 它返回一个元组。创建成功返回True,失败的话False,不执行创建。
>>> author = Author.objects.get_or_create(last_name='fe_cow')
>>> print author
(<Author: fe_cow>, False) # False:说明已经重复 创建失败
>>> author = Author.objects.get_or_create(last_name='cu_cow')
>>> print author
(<Author: cu_cow>, True) # True: 创建成功
2 查询记录
方法一:查询所有对象 (all()方法
返回包含数据库中所有对象的一个查询集
。)
>>> author = Author.objects.all()
>>> print author
<QuerySet [<Author: fecow>, <Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
方法二:过滤查询 (filter()
返回一个新的查询集,它包含满足查询参数的对象。)
>>> author = Author.objects.filter(last_name='cu_cow')
>>> print author
<QuerySet [<Author: cu_cow>]>
方法三:指定查询 (get
查询只能返回一个对象
,多了少了都会引发DoesNotExist 异常)
>>> author = Author.objects.get(id=1)
>>> print author
fecow
方法四:双下划线查询__
;__contains
:包含;__icontains
不区分大小写;__regex
:正则查询;__lt
:小于xxx;__lte
:小于等于xxx;__gt
:大于xxx;__gte
:大于等于xxx;__startswith()
: 以xxx开头,;__istartswith()
:不区分大小写以xxx开头, __endswith()
:以xxx结尾;__iendswith()
:以xxx结尾不区分大小写
- 以上使用方法基本上都一致:
对象
.objects.filter
(属性
__xxx
) 例子如下:
>>> author = Author.objects.filter(id__gte=2)
>>> print author
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
- 单独说一个特殊的
__in
判断字段在列表内。通常用pk指主键,不限于id,适用更好。
>>> author_list = Author.objects.values_list('id', flat=True)
# 返回的是:<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
>>> Author.objects.filter(pk__in=author)
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
方法五:first(), last()获取查询结果中单个对象
>>> Author.objects.filter(id__gte=2)
# 返回结果:QuerySet集合
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
>>> Author.objects.filter(id__gte=2).first()
# 返回结果:objects对象 而且返回第一个对象
<Author: fe_cow>
>>> Author.objects.filter(id__gte=2).last()
<Author: cu_cow>
# 返回结果:objects对象 而且返回的是最后一个对象
方法六:通过values
查询
values('字段')
用字典形式,返回的是指定字段的查询结果;
>>> Author.objects.values('last_name')
<QuerySet [{'last_name': u'fecow'}, {'last_name': u'fe_cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cu_cow'}]>
# 返回字典列表;多个字段间以逗号分隔
values_list('字典')
,返回的也是指定字段的查询结果
>>> Author.objects.values_list('last_name')
<QuerySet [(u'fecow',), (u'fe_cow',), (u'cow',), (u'cow',), (u'cow',), (u'cow',), (u'cu_cow',)]>
# 返回的是元组列表,多个字段也是用逗号分割
values_list('字段', flat=True)
flat=True :之后返回的是值列表
>>> Author.objects.values_list('id', flat=True)
<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
# 返回的是列表
方法六:exclude(**kwargs)
反向过滤
>>> Author.objects.exclude(id__gt=2)
<QuerySet [<Author: fecow>, <Author: fe_cow>]>
# 取反
方法七:exists()
>>> Author.objects.filter(id=2).exists()
True
# QuerySet包含数据返回True
>>> Author.objects.filter(last_name='Au_cow').exists()
False
# QuerySet不包含数据返回False
3 修改记录
方法一:QuerySet.update('字段'='修改的值')
>>> Author.objects.filter(last_name='cu_cow').update(last_name='Ai_cow')
1L
# 修改的前提是先查找,然后调用update(field=val)方法,只有QuerySet集合对象才能调用该方法,也就是说通过get(), first(), last()获取的对象没有该方法。
方法二:对象赋值
>>> author_obj = Author.objects.filter(last_name='fe_cow').first()
>>> author_obj.last_name = 'Fe_cow'
>>> author_obj.save()
# 不推荐使用,效率低
4 删除记录
调用delete()方法
delete()方法支持QuerySet
集合对象的删除,也支持单个对象
的删除。
>>> Author.objects.filter(last_name='fe_cow').delete()
(1L, {u'apps.Book_authors': 0L, u'apps.Author': 1L})
# 默认就是级联删除,对应多对多的表也会删除
QuerySet
- 通过名字我们也能想到从数据库查出来的结果一般是一个集合,哪怕只有一个对象,也叫集合。
QuerySet特性
- 可以进行切片,也可以进行遍历。
>>> Author.objects.filter(id__gt=2)[:2] # 使用切片来获取
# <QuerySet [<Author: fe cow>, <Author: fe cow>]>
>>> authors = Author.objects.filter(id__gt=2) # 使用for循环来获取
>>> for author in authors:
... print author
# 打印结果如下
# fe cow
# fe cow
# fe cow
# fe cow
- 惰性机制: 只有使用QuerySet时,才会走数据库。像
.all()
filter()
时,并不会真正执行数据库查询,只是翻译了SQL语句
;当我们执行if xxx
,print xxx
;for xxx in xxx:
这些操作才会执行SQL语句
,进行数据库查询。 - 缓存机制:
每次
执行了数据库查询
后,会将结果放在QuerySet的缓存
中,下次在使用QuerySet时, 不会走数据库,直接从缓存中拿取数据。比如:
>>> author = Author.objects.all() # 获取所有Author QuerySet中的 last_name
>>> for res in author:
... print res.last_name # Ai_cow cow
>>> Author.objects.create(last_name='COW',first_name='FE') # 接下来往数据库中插入一跳数据
>>>for res in author:
print res.last_name # Ai_cow cow # 发现,已经创建了新的数据,但是表里面没有这条数据
# 以上结果证明了QuerySet缓存的机制,新添加一条记录;打印结果没有发生改变,说明他不会重新走数据库,而是从缓存中获取数据。
>>> author = Author.objects.all() # 获取所有Author QuerySet中的 last_name
>>> for res in author:
... print res.last_name # Ai_cow cow COW1