ORM基础
如果要使用真 mysql 需要去settings 里面将DATABASES 修改成如下
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'books', #你的数据库名称
'USER': 'root', #你的数据库用户名
'PASSWORD': '', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
}
注:
NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
USER和PASSWORD分别是数据库的用户名和密码。
设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
然后,启动项目,会报错:no module named MySQLdb
这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
所以,我们只需要找到项目名文件下的init,在里面写入:
需要在项目名文件下的init.py 在里面写入
import pymysql
pymysql.install_as_MySQLdb()
#重点
增加数据表 就在models.py 里面写
class UserInfo(models.Model):
name = models.CharField(max_length=32,null=True,blank=True,verbose_name='姓名')
username = models.CharField(max_length=32,null=True)
password = models.CharField(max_length=32,null=True)
# num = models.IntegerField(default=0) #定义了一个数字类型,默认值为0
def func(self):
return 'add you baba'
def __str__(self): #查询数据库 返回字符串
return self.name
class School(models.Model): #null=True,blank=True 要用就要一起用
name = models.CharField(max_length=32,null=True,blank=True,verbose_name='学校名')
#null=True 可以为空, blank 针对admin使用的时候这两个同时使用可以为空。verbose_name 显示信息
# mac = models.URLField(max_length=128,null=True,blank=True,verbose_name='地址')
# email = models.EmailField(max_length=128,null=True,blank=True,verbose_name='邮箱')
# true_false = models.BooleanField(max_length=128,null=True,blank=True,verbose_name='是否')
# date = models.DateField(verbose_name='时间')
# cla = models.ForeignKey(to='Class',default=1) #default='1',设置默认值 # ForeignKey 一对多类型。
#自动生成ID --> cla_id ,指向了Class 类,它里面会自己生成ID,是class的ID
def __str__(self):
return self.name
class Number(models.Model):
num = models.OneToOneField(to='UserInfo') # 一对一的一一对应关系
# OneToOne 类型对应 UserInfo ,每个学生都有一个学号
def __str__(self):
return self.num
class Class(models.Model):
xuexiao = models.ForeignKey(to='School', default=1)
name = models.CharField(max_length=128,null=True,blank=True,verbose_name='班级')
user = models.ManyToManyField(to='UserInfo',related_name='clauser') # 多对多关系
# class_to_userinfo --> id , UserInfo_id , class_id 三张表
def __str__(self):
return self.name
def __str__(self):
__str__()方法,返回一个好看的字符串就可以了:
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __str__(self):
... return 'Student object (name: %s)' % self.name
...
>>> print Student('Michael')
Student object (name: Michael)
这样打印出来的实例,不但好看,而且容易看出实例内部重要的数据。
但是细心的朋友会发现直接敲变量不用print,打印出来的实例还是不好看:
>>> s = Student('Michael')
>>> s
<__main__.Student object at 0x109afb310>
这是因为直接显示变量调用的不是__str__()
,而是__repr__()
,两者的区别是__str__()
返回用户看到的字符串,而__repr__()
返回程序开发者看到的字符串,也就是说,__repr__()
是为调试服务的。
解决办法是再定义一个__repr__()
。但是通常__str__()
和__repr__()
代码都是一样的,所以,有个偷懒的写法:
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name=%s)' % self.name
__repr__ = __str__
__str__()
返回用户看到的字符串,
__repr__()
返回程序开发者看到的字符串,
__repr__()
是为调试服务的。
增删改查-----查询
两种查询方式
第一种 .all()
第二种 .get(id=?) 或者 .filter() 里有 .first() 和 .last()
.get 取的是 queryset 集合
.filter 取的是 queryslit 列表
查的时候推荐用 .filter
models.School.objects.all()
#查询所有 是一个queryslit 里面每一个值都是queryset
b = models.School.objects.all()
#返回所有信息 all()出来的是 queryset_list
这个是个list的里面有很多的queryset
models.School.objects.all()
b = models.School.objects.all()
print (b) # 打印这个输出QuerySet
print (type(b)) #看这个是什么类别
for i in b:
print (i.name,type(i),i) #循环输出这个list里面的信息
print (b)
, ]>
print (type(b))
for --> print (i.name,type(i),i) # 这里输出的是 类
你爸爸大学 你爸爸大学
五道口职业学院 五道口职业学院
c = models.School.objects.get(id=1) # get通过id 拿到的是queryset 的值,只能取ID
print (c) ---> 你爸爸大学
d = models.School.objects.filter(name='五道口职业学院').first()
e = models.School.objects.filter(name='你爸爸大学').last()
print (d,e) ---> 五道口职业学院, 你爸爸大学
d = models.School.objects.filter(name='abc').first()
e = models.School.objects.filter(name='avx').last() #如果没有这个值 这会返回 None
print (d,e) ---> None None
以字典的形式去取值
dict1 = {'name':'hc'}
ojb = models.School.object.filter(**dict1).first()
print (ojb) ---> None
dict1 = {'name':'你爸爸大学'}
ojb = models.School.object.filter(**dict1).first()
print (ojb) ---> 你爸爸大学
查询
查询相关API:
filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
all(): 查询所有结果
get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------
values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 ;-->拿到库内 固定列内的 值作为 一对 key value ;如果条件是多个,那就拿到多对,整体是一个列表
exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
order_by(*field): 对查询结果排序
reverse(): 对查询结果反向排序
distinct(): 从返回结果中剔除重复纪录
values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列;相比于 values 左后是一个 元祖,不是字典
count(): 返回数据库中匹配查询(QuerySet)的对象数量。
first(): 返回第一条记录
last(): 返回最后一条记录
exists(): 如果QuerySet包含数据,就返回True,否则返回False
双下划线(__)之单表条件查询
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
startswith,istartswith, endswith, iendswith,
增,改,删 (1,2)
create ,update, delete
增加 create
create方式一: Author.objects.create(name='Alvin')
create方式二: Author.objects.create(**{"name":"alex"})
save方式一: author=Author(name="alvin")
author.save()
save方式二: author=Author()
author.name="alvin"
author.save()
改的第一种方式 update ,推荐
第二种方式 通过get ,找不到会报错
需要先用get查,然后使用点,点出来再重新修改,最后save() 保存 .name()
obj_c = models.School.objects.cteate(name='hc') #name 是字段信息
print (obj_c)
obj_d = models.School.objects.filter(name='hc').delete() #先查询,再删
print (obj_d)
改的第一种方式 update ,推荐
obj_u = models.School.objects.filter(name='hc').updata(name='hc1') #先查询,再修改
print (obj_u) # 这里只会拿到修改的条数
改的第二种方式 ,通过get ,如果找不到会报错
obj_g = models.School.objects.get(name='hc') #先通过get找到对应的字段,如果找不到会报错
obj_g.name='hc2' # 用这个queryset对象再字段点出来 --> .name 再重新赋值给它,即为修改
obj_g.save() #最后用到这个 save() 方法将其保存写入到数据库
注意:
第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。
在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。
dic = {'name':'hc1'}
# 增加 'hc','hc1'
for i in ['hc','hc1']:
obj_c = models.School.objects.create(name=i)
#name 是字段信息,对应字段直接加数据
print (obj_c,type(obj_c))
# 删除 hc
obj_d = models.School.objects.filter(name='hc').delete()
#先查询,再删
print (obj_d,type(obj_d))
# 这里只会拿到删除的条数
# 更新 1 update --> hc2
obj_u = models.School.objects.filter(**dic).update(name='hc2')
#先查询,再修改
print (obj_u,type(obj_u)) # 这里只会拿到修改的条数
# 更新 2 get --> hc3
obj_g = models.School.objects.get(name='hc2')
#先通过get找到对应的字段,如果找不到会报错
obj_g.name = 'hc3'
# 用这个queryset对象再字段点出来 --> .name 再重新赋值给它,即为修改
obj_g.save()
#最后用到这个 save() 方法将其保存写入到数据库
print(obj_g,type(obj_g))
#输出
print (obj_c,type(obj_c))
hc
hc1
print (obj_d,type(obj_d))
(1, {'hc.School': 1}) #修改的条数
print (obj_u,type(obj_u))
1 #修改的条数
print(obj_g,type(obj_g))
hc3