Django Model 进阶
回顾:
定义 models
settings.py激活app才能使用models
migrations:版本控制,当更改库表结构时可以处理数据
增删改查
常见Field
模型的价值在于定义数据模型,使用Python的形式操作数据库
from django.db import models class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
转换为sql
CREATE TABLE IF NOT EXISTS myapp_person(
id INT(11) NOT NULL AUTO_INCREMENT,
first_name VARCHAR(30) DEFAULT NULL,
last_name VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
关系:
一对多 ForeignKey,如厂商和汽车关系
多对多 ManyToManyField,如用户和组关系
一对一 OneToOneField,如饭店和地址关系
# 多对一关系
class Manufacturer(models.Model):
pass
class Car(models.Model):
manufacturer = models.ForeignKey('Manufacturer') # 多对多关系
class Group(models.Model):
pass
class User(models.Model):
groups = models.ManyToManyField('Group') # 一对一关系
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(models.Model):
place = models.OneToOneField('Place', primary_key=True)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
重写save()方法:
如保存记录之前,写入日志操作,注意一定要记得调用超类的save()方法,否则不会保存到数据库
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() def save(self, *args, **kwargs):
print('do something')
super(Blog, self).save(*args, **kwargs)
print('do something else')
模型继承:
- 抽象基类
只想使用父类来持有一些信息,不想在每个子模型中都敲一遍,这个类永远不会单独使用,使用abstract表明基类,数据库不会建该表
如auth模块 User继承(AbstractUser)
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
ordering = ['name'] class Student(CommonInfo):
home_group = models.CharField(max_length=5)
class Meta(CommonInfo.Meta):
db_table = 'student_info'
说明:
Meta 也可以继承,如果子类不实现Meta则默认会继承
- 多表继承
继承一个存在的模型,每个模型都有自己的数据库表。每一个层级下的每个model都是一个真正意义上完整的model,
每个model都有专属的数据表,都可以查询和创建数据表,
继承关系在子model和它的每个父类之间都添加一个链接(通过自动创建的OneToOneField来实现)
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80) class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
- 代理继承
使用多表继承时,model的每个子类都会自动创建一张新数据表,通常情况下,这正是我们想要的操作,
这是因为子类需要一个空间来存储不包含在基类中的字段数据。但有时,可能只想更改model在Python层的行为实现,
比如:更改默认的manager,或是添加一个新方法
代理继承可以做到:为原始模型创建一个代理。可以创建、删除、更新代理model的实例,而且所有数据都可以像使用原始model一样保存
不同之处在于:可以在代理model中改变默认的排序设置和默认的manager,不会对原始model产生影响
设置 Meta类中proxy的值为True,就完成了对代理model的声明
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30) class MyPerson(Person):
class Meta:
proxy = True def do_something(self):
pass
说明:
MyPerson只是一个代理,数据库中不会建立该表,MyPerson类和它的父类Person操作同一个数据表,
特别的是,Person的任何实例也可以通过MyPerson访问,反之亦然

- 多重继承
多重继承和多表继承没什么大的差别,会自动添加两个OneToOneField,
需要指出,两个基类的默认自增id要重新命名,否则添加OneToOneField会有问题,也不允许子类重写父类字段
class Article(models.Model):
article_id = models.AutoField(primary_key=True) class Book(models.Model):
book_id = models.AutoField(primary_key=True) class BookReview(Book, Article):
pass
创建记录时,父类的各个字段需要填写
b = BookReview.objects.create(headline='T' , body='body' , title=' title')
Model querys
回顾:
简单增删改查
返回结果 object QuerySets
exclude
反向查询 b.entry_set.all() 可起别名,返回QuerySets
复杂查询 Q
跨关联关系查询,__
QuerySet链式过滤
F查询
限制返回个数
查询对象比较
比较两个model实例,实质在后台,它会比较两个模型主键的值

所有查询api
https://docs.djangoproject.com/en/1.11/ref/models/querysets/
进阶:
1. annotate添加注释属性 与聚合函数一起使用返回聚合值,如统计问题的个数,q就有了choice_num这个属性

2. aggregate 聚合函数返回结果字典

3. 聚合类函数,或注释函数,在django.db.models模块中
class Avg(expression, output_field=FloatField, **extra)
class Count(expression, distinct=False, **extra)
class Max(expression, output_field=None, **extra)
class Min(expression, output_field=None, **extra)
class Sum(expression, output_field=None, **extra)
class StdDev(expression, sample=False, **extra) # 标准差
class Variance(expression, sample=False, **extra) # 方差
4. distinct() 去重
5. values 返回ValuesQuerySet(类字典),而不是模型实例对象
6. vlaues_list与values类似,但返回元组而不是字典
7. defer only
8. using使用哪个数据库
9. select_for_update 返回一个queryset,会锁定相关行直到事务结束
在支持的数据库上面产生一个 SELECT...FOR UPDATE

10. raw 执行原始sql
11. get_or_create,有就获取;没就新增,注意返回结果类型和参数defaults含义
try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
obj = Person.objects.get(first_name='John', last_name='Lennon', birthday=(1993, 7, 1))
# Equal
obj, created = Person.objects.get_or_create(
first_name = 'John',
last_name = 'Lennon',
defaults={'birthday': date(1993, 7, 1)})
12. update_or_create
13. bulk_create
14. in_bulk
15. latest、earliest、first、last
事务:
事务是绑定在view中实现的
from django.db import transaction @transaction.non_atomic_requests
def my_view(request):
print('do_stuff') @transaction.atomic
def viewfunc(request):
print('do_stuff') '''
警告!!!
虽然这种事务模式的优势在于它的简单性,但在访问量增长到一定的时候会造成很大的性能损耗。
这是因为为每一个视图开启一个事物会有一些额外的开销。
另外,这种性能影响还取决于你的应用程序的查询模式以及你的数据库对锁的处理是否高效。
'''
自定义管理器:
- 添加额外管理器方法
默认objects添加自定义方法,方法需写原生sql。
添加额外管理器方法是类增加“表级”功能的首选方式(如果要添加行级功能,比如只对某个模型的实例起作用,应使用模型方法,而不是管理器方法)
额外管理器方法可以返回你想要的任何数据,而不需要返回一个查询及集
例如,下面这个自定义管理器提供一个with_counts()方法,它返回所有OpinionPoll对象的列表,列表的每项都有一额外num_reponses属性,
该属性保存一个聚合查询的结果(注:对应的是SQL查询语句中的COUNT(*)生成的项)
# 添加额外管理器方法
class PollManager(models.Manager):
def with_counts(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
SELECT p.id, p.question, p.poll_date, COUNT(*)
FROM polls_opinionpoll p, polls_resopnse r
WHERE p.id = r.poll_id
GROUP BY p.id, p.question, p.poll_date
ORDER BY p.poll_date DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1], poll_date=row[2])
p.num_responses = row[3]
result_list.append(p)
return result_list class OpinionPoll(models.Model):
question = models.CharField(max_length=200)
poll_date = models.DateField()
objects = PollManager() # 关键点*** class Response(models.Model):
poll = models.ForeignKey('OpinionPoll')
person_name = models.CharField(max_length=50)
response = models.TextField()
- 添加自定义manager
简单的说,就是在模型里添加属性=models.Manager(),或者它的自定义子类,从而实现对库表的操作
class AuthorManager(models.Manager):
def get_queryset(self):
return super(AuthorManager, self).get_queryset().filter(role='A') class EditorManager(models.Manager):
def get_queryset(self):
return super(EditorManager, self).get_queryset().filter(role='E') class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', 'Author'), ('E', 'Editor')))
people = models.Manager() # 等同于原始 objects
authors = AuthorManager()
editros = EditorManager() Person.objects.all()
Person.people.all()
Person.authors.all()
Person.editros.all()
Django Model 进阶的更多相关文章
- Django model进阶
Django-model进阶 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Ent ...
- Django——model进阶(待完成)
https://www.cnblogs.com/yuanchenqi/articles/7570003.html 一.QuerySet 1.可切片 使用Python 的切片语法来限制查询集记录的数目 ...
- Django框架学习-Model进阶用法
Model进阶用法 回顾 访问外键 访问多对多关系 更改数据库结构 当处理数据库结构改变时,需要注意到几点: 增加字段 首先在开发环境中: 再到产品环境中: 删除字段 删除多对多字段 删除model ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python开发【第二十二篇】:Web框架之Django【进阶】
Python开发[第二十二篇]:Web框架之Django[进阶] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 ...
- Python之路,Day15 - Django适当进阶篇
Python之路,Day15 - Django适当进阶篇 本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣 ...
- Django model select的各种用法详解
<Django model update的各种用法介绍>文章介绍了Django model的各种update操作,这篇文章就是她的姊妹篇,详细介绍Django model select的用 ...
- Django 2.0 学习(07):Django 视图(进阶-续)
接Django 2.0 学习(06):Django 视图(进阶),我们将聚焦在使用简单的表单进行处理和精简代码. 编写简单表单 我们将用下面的代码,来替换之前的detail模板("polls ...
随机推荐
- win10 linux 子系统 所在 目录
C:\Users\用户名\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\r ...
- Bash常用快捷键及其作用
在 Bash 中有非常多的快捷键,如果可以熟练地使用这些快捷键,可有效地提高我们的工作效率.只是快捷键相对较多,不太好记忆,这就要多加练习和使用.这些快捷键如表 1 所示. 表 1 Bash 常用快捷 ...
- django 数据库查询的几个知识点
django查询db过程中遇到的几个问题: 1. 数据库切换,用using products = models.TProductCredit.objects.using(') 2.查询结构集是Quer ...
- windows下Mysql8.0.12安装详解
MySQL的安装过程还是比较繁琐,为了以后安装节约时间,将其详细安装过程总结如下: 1>下载对应版本 下载地址:https://dev.mysql.com/downloads/mysql/ 2& ...
- SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作
在开发或者测试环境的数据库中,经常会发现有开发或者测试人员误删除表或者数据的情况,对于开发或者测试库,一般都没有安排定时的备份任务去备份数据库,一方面是由于存储资源有限,不太可能给开发或者测试环境准备 ...
- CSS 图像大小
CSS 图像大小 虽然在HTML中,img标签有属性height.width设置高和宽,在工作中却使用得非常少,通常使用CSS来控制大小. 给盒子设置属性height.width限制大小.单位通常是像 ...
- Kafka自带zookeeper报错INFO Got user-level KeeperException when processing xxx Error Path:/brokers Error:KeeperErrorCode = NodeExists for /brokers (org.apache.zookeeper.server.PrepRequestProcessor)
问题描述: 按照kafka官方文档的操作步骤,解压kafka压缩包后.依次启动zookeeper,和kafka服务 kafka服务启动后,查看到zookeeper日志里有以下异常 问题原因及解决办法: ...
- 初学c# -- 学习笔记(9) 关于SQL2008
在做一个局域网的类似网盘的学习练习,服务端差不多了,在改bug.用vlc的dll做的全格式视频.音频预览在线播放下载等等. 在做服务端也遇到了一些问题,走了好多弯路. 开始把上传的视频.音频.图像.文 ...
- 小强学渲染之OpenGL的GPU管线
GPU渲染流水线,是硬件真正体现渲染概念的操作过程,也是最终将图元画到2D屏幕上的阶段.GPU管线涵盖了渲染流程的 几何阶段 和 光栅化阶段,但对开发者而言,只有对顶点和片段着色器有可编程控制权,其他 ...
- 2015-2016 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2015)
题目链接 : http://codeforces.com/gym/100781/attachments A-Adjoin the Network 题意大概是有多棵树(也可能是一颗),现在要把它们合并 ...