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 ...
随机推荐
- scrapy-pipeline的方法
scrapy中多个pipeline作用: 一个项目可能需要爬取多个网站,根据每个网站的数据量(处理方式)不同,可创建多个管道 pipeline class SpideranythingPipeline ...
- 来自Github的优秀源码(python操作iframe框架网页)
#Please use your username and password for academia in codeimport timefrom selenium import webdriver ...
- shell脚本可以解决的问题
1.各类监控脚本,文件,内存,磁盘,端口 url 监控报警 2.监控网站目录文件是否被篡改,以及如何恢复 3.如何开发各类服务rsync nginx mysql等启动停止脚本 4.开发mysql主从复 ...
- 渲染函数render和函数式组件
vnode对象 vnode对象包括(vnode并不是vue实例,而是vue实例中渲染函数render执行后生成的结果) this.tag = tag // 当前节点标签名 this.data = da ...
- This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.
This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.
- Thinkphp语句拼接
例如查询Stu表中年龄大于18,或者身高低于180cm的男性(1为男性),(例子不太好标题有可能不符,望见谅) $where['age'] = array("gt",18); $w ...
- [C语言]进阶|数据类型: 整数, 浮点, 逻辑, 类型转换和条件运算
--------------------------------------------------------------------------------- [C语言的类型] 1. 整型(都分为 ...
- AOP方法增强自身内部方法调用无效 SpringCache 例子
开启注解@EnableCaChing,配置CacheManager,结合注解@Cacheable,@CacheEvit,@CachePut对数据进行缓存操作 缺点:内部调用,非Public方法上使用注 ...
- VueJs相关命令
参考: https://www.jianshu.com/p/1626b8643676 安装axios $ npm install axios 如何打包 基于Vue-Cli,通过npm run ...
- Python设计模式 - UML - 类图(Class Diagram)
简介 类图是面向对象分析和设计的核心,用来描述系统各个模块中类与类之间.接口与接口之间.类与接口之间的关系,以及每个类的属性.操作等特性,一般在详细设计过程中实施. 类图本身就是现实世界的抽象,是对系 ...