一、配置数据库
settings.py
DTABAESE = {
'default':{
'ENGINE':'dajngo.db.backends.mysql',
'NAME':'test',
'HOST':'127.0.0.1',
'PORT':3306,
'USER':'root',
'PASSWORD':'123456',
}
}
init.py
import pymysql
pymysql.install_as_MySQLdb()
二、ORM模型
使用ORM模型
当项目越来越大的时候,就会出现很多原生SQL语句,就会出现以下问题:
1.SQL语句重复使用率不高,越复杂的sql语句就越长,会出现很多类似的SQL语句
2.很多SQL语句都是业务逻辑拼凑出来的,如果有数据库发生改变就要去修改这些sql语句中的逻辑,会容易漏掉SQL的更改
3.原生SQL语句没有考虑安全
使用ORM的好处
1.易用性:减少复杂SQL出现的概率,是业务更加的直观
2.设计灵活:可以简单的写出复杂的SQL
3.可移植性:底层封装了对多种数据库的实现,一旦更改数据库,只需更改用户账号、密码。。。
关系映射
模型类
---->>>数据库一张b表
属性
--->>>表中的字段名称和属性 约束条件
方法
--->>>类中的普通方法
数据库中的一条数据
--->>>一个对象
注意:
在ORM上对于对象的属性的操作,就是对一条数据中的某个字段进行操作,不直接操作数据库,操作ORM,ORM底层最终转换为SQL语句
三、定义属性
概述:
django根据属性的类型确定一下信息:
1.当前选择的数据库支持的字段类型
2渲染管理表单时使用的默认html控件
3.在管理站点最低限度的验证
注意:
django 会在表中自动增加主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的逐渐列
库
定义库时,需要字段类型,字段类型被定义在djngo.db.models.fields目录下,为了方便使用,被导入到django.db.models中
使用方式:
导入:
from django.db import models
通过models.Field创建字段类型的对象,赋值给属性
逻辑删除
对于重要的数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
字段类型
AutoField
一个根据实际ID自动增长的IntegerField,通常不指定如果不指定,一个主键字段将自动添加到模型中
CharField(max_length=字符串长度)
字符串,默认的表单样式是TextInput
TextField
大文本字段,一般超过4000使用,默认的表单控件是Textarea
IntegerField
整数
DecimalField(max_digits=None,decimal_places=None)
c参数说明DecimalField.max_digits
位数总数
DecimalField.decimal_places
小数位后的数字位数
FloatField
用Python的float实例来表示的浮点数
BooleanField
true/false字段,此字段的表单控制是CheckboxInput
NullBooleanField
支持null、true、false三种值
DateField([auto_now=False,auto_now_add=False])
使用Python的datetime.date实例表示的日期
参数说明:
DateField.auto_now
:每次保存对象时,自动设置该字段为当前时间,用于‘最后一次修改’的时间戳,它总是使用用当前时间日期,默认为false
DateField.auto_now_add
:当对象第一次被
创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
常见问题:
如何将创建时间设置为“默认当前”并且可修改
在现实生产环境中,往往希望对象的创建时间默认设置为当前值,但又希望日后可以修改它,如何实现这种需求的呢。
django中所有的model字段都拥有一个default参数,用来给字段设置默认值(上面的文档中有介绍)。
我们可以使用default=timezone.now()来替换auto_now=True或auto_now_add=True。
(default=timezone.now 对应 django.utils.timezone.now())
from django.db import models
import django.utils.timezone as timezone
class Test(models.Model):
add_date = models.DateTimeField('保存日期',default = timezone.now)
mod_date = models.DateTimeField('最后修改日期', auto_now = True
注意:
auto_now_add,auto_now和default这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
Timefield
使用Pythonde datetime.time实例表示的时间,参同DateField
DateTimeField
使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
FileField
一个上传文件的字段
ImageField
继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
四、字段约束
概述:
1.通过字段选项,可以实现对字段的约束
2.在字段对象使用时通过关键字参数指定
null
:如果为True , dajngo将空值一NULL存储到数据库中,默认值是False
blank
如果为True,则则该字段允许为空白,默认值是False
null是数据库范畴的概念,blank是表单验证范畴的
注意: blank只对TextField这样的生效,对数字不生效,会报错
db_column
字段的名称,如果为指定,则使用属性的名称
db_index
若值为True,则在表中会为此字段创建索引
default
默认值
primary_key
若为True,则该字段会成为明星的主键字段
unique
如果为True,这个字段在表中必须有唯一值
更改表明
# 在Model中
class Meta:
db_table = "new_tablename" # 更改表名
将模型迁移到库中
1.创建迁移文件(此刻表并没有创建到库中)
python manage.py makemigrations
2.执行迁移(将模型创建到库中)
python manage.py migrate
注意:
以上操作都不需要直接操作数据库
五、模型成员
类属性
(1)object
是Manage类的一个对象
作用:与数据库进行交互
当创建模型类 并且没有指定模型管理器的时候 默认为object
(2)自定义模型管理器
class Test(model.Model):
.....
testobj = models.Manager()
使用
def select(req):
Test.testobj.get(pk=1)
注意:
默认的objects不存在了
四、自定义管理器Manager类
继承Manager类,重学查询方法get_queryset方法,将查询集按照自己的需求添加过滤筛选条件
一个模型类,可以有多个模型管理器
当创建模型类对象时,django不会对数据库进行读写操作,调用save()方法才与数据库交互,进行insert或update操作,将数据保存到数据库中。如果模型类的属性比较多,逐个属性赋值很麻烦,推荐使用管理器
实例:
models.py
class UserManager(models.Manager):
def get_queryset(self): # 查询执行的就是当前的方法,更改当前模型管理器查询数据返回的结果
return super().get_queryset().filter(sex=True) # 返回性别为True的数据
# 使用
# 创建用户模型类
class User(models.Model):
username = models.CharField(max_length,db_indexTrue,default='张三')
password = models.CharField(max_length=128,default='123456')
sex = models.BooleanField(default=True)
age = models.IntegerField(default=20)
info = models.CharFileld(max_length=100,default='个人简历')
icon = models.CharField(max_Length=70,default='default.jpg')
userobj = models.Manger() # 自定义模型管理器的名称为 userobj 原来默认的object则不存在
getSet = UserManager() # 当前管理器的查询结果为性别为True的数据
def __str__(self):
return self.usernmae
在view.py中使用
def select(req):
u = User.userobj.fielter() # filelt作用 查询所有(如果没有给过滤条件时)
# u = User.userobj.fielter(sex=True) # fielter作用 查询所有sex为True的
# for row in u:
#print(row)
# return HttpResponse('查询所有数据')
u = User.getSet.fielter()
return render(req,'show.html',{'obj':u})
模板show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
table{
border-collapse: collapse;
margin: auto;
}
td,th{
width: 150px;
text-align: center;
height: 40px;
}
</style>
</head>
<body>
<table>
<caption><h2>数据查询</h2>
<tr>
<th>用户名</th>
<th>密码</th>
<th>性别</th>
<th>年龄</th>
<th>个人简介</th>
<th>头像</th>
</tr>
{% for row in obj %}
<tr>
<td>{{ row.username }}</td>
<td>{{ row.password }}</td>
<td>
{% if row.sex %}
男
{% else %}
女
{% endif %}
</td>
<td>{{ row.age }}</td>
<td>{{ row.info }}</td>
<td>{{ row.icon }}</td>
</tr>
{% endfor%}
</caption>
</table>
</table>
</body>
</html>