一、Django连接数据库操作
1、创建数据库 (注意设置 数据的字符编码)
由于Django自带的orm是data_first类型的ORM,使用前必须先创建数据库
create database ayalysis default character set utf8 collate utf8_general_ci;
2、修改project中的settings.py文件中设置 连接 MySQL数据库(Django默认使用的是sqllite数据库)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'ayalysis',
'USER': 'totd',
'PASSWORD': 'totd890',
'HOST': '192.168.182.128',
'PORT': '3306',
}
}
3、查看orm操作执行的原生SQL语句,在project中的settings.py文件增加
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
4、修改project 中的__init__py 文件设置 Django默认连接MySQL的方式
import pymysql
pymysql.install_as_MySQLdb()
5、setings文件注册APP
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
]
6、进行数据迁移,在winds cmd或者Linux shell的项目的manage.py目录下执行
python manage.py makemigrations #根据app下的migrations目录中的记录,检测当前model层代码是否发生变化?
python manage.py migrate #把orm代码转换成sql语句去数据库执行
python manage.py migrate --fake #只记录变化,不提交数据库操作
二、字段类型
Django提供了很多字段类型,比如URL/Email/IP/ 但是mysql数据没有这些类型,这类型存储到数据库上本质是字符串数据类型,其主要目的是为了封装底层SQL语句
1. 字符串类
name=models.CharField(max_length=32)
- EmailField(CharField):
- IPAddressField(Field)
- URLField(CharField)
- SlugField(CharField)
- UUIDField(Field)
- FilePathField(Field)
- FileField(Field)
- ImageField(FileField)
- CommaSeparatedIntegerField(CharField)
models.CharField 对应的是MySQL的varchar数据类型
MySQL知识点补充:
char 和 varchar的区别 :
共同点是存储数据的长度,不能 超过max_length限制;
不同点是varchar能根据数据实际长度存储,char按指定的max_length来存储数据;所有前者更节省硬盘空间。
2. 时间字段(详细使用)
- models.DateTimeField(null=True)
- models.DateField()
- models.TimeField() # 不常用
3、数字字段
(max_digits=30,decimal_places=10)总长度30小数位 10位)
- models.IntegerField() # 数字
- models.FloatField() # 浮点
- models.DecimalField(max_digits=8,decimal_places=3) # 精确浮点
4、枚举字段
choice=(
(1, '男'),
(2, '女'),
(3, '其他')
)
gender=models.IntegerField(choices=choice) # 枚举类型
扩展:在数据库存储枚举类型,比外键有什么优势?
1、无需连表查询性能低,省硬盘空间(选项不固定时用外键)
2、在modle文件里不能动态增加(选项一成不变用Django的choice)
5、其他字段
db_index = True 表示设置索引
unique(唯一的意思) = True 设置唯一索引
联合唯一索引
class Meta:
unique_together = (
('email','ctime'),
)
联合索引(不做限制)
index_together = (
('email','ctime'),
)
ManyToManyField(RelatedField) #多对多操作
三、字段参数介绍
- 数据库级别生效
- Django admin级别生效
针对 dango_admin生效的参数(正则匹配)(使用Django admin就需要关心以下参数!!))
- blank #是否为空
- editable=False # 是否允许编辑
- help_text="提示信息" # 提示信息
- choices=choice # 提供下拉框
- error_messages="错误信息" # 错误信息
- validators # 自定义错误验证(列表类型),从而定制想要的验证规则(EmailValidator,URLValidator,DecimalValidator,MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator)
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
四、单表操作
1. ORM使用方式
ORM操作可以使用类实例化,obj.save()的方式,也可以使用create()的形式
2. QuerySet数据类型介绍
- QuerySet与惰性机制:
所谓惰性机制指Userinfo.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。 - QuerySet特点:
<1>可迭代的
<2>可切片
<3>惰性计算和缓存机制
def queryset(request):
books=models.Book.objects.all()[:10] #切片 应用分页
books = models.Book.objects.all()[::2]
book= models.Book.objects.all()[6] #索引
print(book.title)
for obj in books: #可迭代
print(obj.title)
books=models.Book.objects.all() #惰性计算--->等于一个生成器,不应用books不会执行任何SQL操作
# query_set缓存机制1次数据库查询结果query_set都会对应一块缓存,再次使用该query_set时,不会发生新的SQL操作;
#这样减小了频繁操作数据库给数据库带来的压力;
authors=models.Author.objects.all()
for author in authors:
print(author.name)
print('-------------------------------------')
models.Author.objects.filter(id=1).update(name='张某')
for author in authors:
print(author.name)
#但是有时候取出来的数据量太大会撑爆缓存,可以使用迭代器优雅得解决这个问题;
models.Publish.objects.all().iterator()
return HttpResponse('OK')
3. 增删改查操作
- 增
orm添加一条记录的方法
def orm(request):
# 单表
# 1、表.objects.create()
models.Publish.objects.create(name='浙江出版社',addr="浙江.杭州")
models.Classify.objects.create(category='武侠')
models.Author.objects.create(name='金庸',sex='男',age=89,university='东吴大学')
# 2、类实例化:obj=类(属性=XX) obj.save()
obj=models.Author(name='吴承恩',age=518,sex='男',university='龙溪学院')
obj.save()
# 1对多
# 1、表.objects.create()
models.Book.objects.create(title='笑傲江湖',price=200,date=1968,classify_id=6, publish_id=6)
# 2、类实例化:obj=类(属性=X,外键=obj)obj.save()
classify_obj=models.Classify.objects.get(category='武侠')
publish_obj=models.Publish.objects.get(name='河北出版社')
# 注意以上获取得是和 book对象 向关联的(外键)的对象
book_obj=models.Book(title='西游记',price=234,date=1556,classify=classify_obj,publish=publish_obj)
book_obj.save()
# 多对多
# 如果两表之间存在双向1对N关系,就无法使用外键来描述其关系了;只能使用多对多的方式,新增第三张表关系描述表;
book=models.Book.objects.get(title='笑傲江湖')
author1=models.Author.objects.get(name='金庸')
author2=models.Author.objects.get(name='张根')
book.author.add(author1,author2)
# 书籍和作者是多对多关系,
# 切记:如果两表之间存在多对多关系,例如书籍相关的所有作者对象集合,作者也关联的所有书籍对象集合
book=models.Book.objects.get(title='西游记')
author=models.Author.objects.get(name='吴承恩')
author2 = models.Author.objects.get(name='张根')
book.author.add(author,author2)
# add() # 添加
# clear() # 清空
# remove() # 删除某个对象
return HttpResponse('OK')
根据条件判断,增加?更新?
# 根据user=user去查找,如果找到更新 如果没有找到创建defaults={} 中的数据
tk = gen_tcoken(username)
models.Token.objects.update_or_create(user=user, defaults={'token': tk})
- 删
# 删除指定条件的数据
models.Tb1.objects.filter(name='seven').delete()
- 改
def delete(request):
# 修改方式1 update()
ret = models.Book.objects.filter(id=1).update(price=3)
# 修改方式2 obj.save()
book_obj=models.Book.objects.get(id=1)
book_obj.price=5
book_obj.save()
- 查
def ormquery(request):
# query_set对象集合 [对象1、对象2、.... ]
books=models.Book.objects.all()
books=models.Book.objects.filter(id__gt=2,price__lt=100)
# 单个对象,没有找到会报错
book=models.Book.objects.get(title__endswith='金')
book1 = models.Book.objects.filter(title__endswith='金').first()
book2 = models.Book.objects.filter(title__icontains='瓶').last()
# query_set字典集合 [{一条记录},{一条记录} ]
books=models.Book.objects.values(
'title','price',
'publish__name',
'date',
'classify__category', # 正向连表: 外键字段___对应表字段
'author__name', # 反向连表: 小写表名__对应表字段
'author__sex', # 区别: 正向 外键字段__,反向 小写表名__
'author__age',
'author__university')
books=models.Book.objects.values('title','publish__name').distinct()
# exclude 按条件排除。。。
# distinct()去重, exits()查看数据是否存在? 返回 true 和false
a=models.Book.objects.filter(title__icontains='金')
return HttpResponse('OK')
连表查询
# 反向连表查询:
# 1、通过object的形式反向连表, obj.小写表名_set.all()
publish=models.Publish.objects.filter(name__contains='湖南').first()
books=publish.book_set.all()
for book in books:
print(book.title)
# 通过object的形式反向绑定外键关系
authorobj = models.Author.objects.filter(id=1).first()
objects = models.Book.objects.all()
authorobj.book_set.add(*objects)
authorobj.save()
# 2、通过values双下滑线的形式,objs.values("小写表名__字段")
# 注意对象集合调用values(),正向查询是外键字段__XX,而反向是小写表名__YY看起来比较容易混淆;
books=models.Publish.objects.filter(name__contains='湖南').values('name','book__title')
authors=models.Book.objects.filter(title__icontains='我的').values('author__name')
print(authors)
# fifter()也支持__小写表名语法进行连表查询:在publish标查询 出版过《笑傲江湖》的出版社
publishs=models.Publish.objects.filter(book__title='笑傲江湖').values('name')
print(publishs)
# 查询谁(哪位作者)出版过的书价格大于200元
authors=models.Author.objects.filter(book__price__gt=200).values('name')
print(authors)
# 通过外键字段正向连表查询,出版自保定的书籍;
city=models.Book.objects.filter(publish__addr__icontains='保定').values('title')
print(city)
五、ORM连表操作
在django使用orm的时候,我们可以把一对多,多对多,分为正向和反向查找两种方式。
- 正向查找:
ForeignKey在 UserInfo表中,如果从UserInfo表开始向其他的表进行查询,这个就是正向操作,反之如果从UserType表去查询其他的表这个就是反向操作。
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表) - 正向连表操作总结:
所谓正、反向连表操作的认定无非是Foreign_Key字段在哪张表决定的,Foreign_Key字段在哪张表就可以哪张表使用Foreign_Key字段连表,反之没有Foreign_Key字段就使用与其关联的 小写表名;
1对多:对象.外键.关联表字段,values(外键字段__关联表字段)
多对多:外键字段.all()
- 反向连表操作总结:
通过value、value_list、fifter 方式反向跨表:小写表名__关联表字段
通过对象的形式反向跨表:小写表面_set().all()
网友评论