Django 模型操作
额外包
mysqlclient :mysql需求 pymysql :mysql需求 pillow :图片文件需求
class FileLibrary(models.Model):# 文件名name = models.CharField(max_length=100)
修改模型后的操作
python manage.py makemigrations
【app名称】,migrations中创建或修改模型对应文件
python manage.py migrate
,将这些改变更新到数据库中。
字段类型
AutoField | 自增字段,通常不用自己设置 |
Booleanfield | 布尔字段,值为True或False |
NullBooleanField | 布尔字段,包含空值:Null、True、False |
CharField | 字符串,必须有max_length表示最大字符个数 |
TextField | 大文本字段,一般超过4000个字符时使用 |
JSONField |
以JSON格式存储 |
URLField | 存储URL的字符串,默认长度200;verify_exists(True),检查URL可用性 |
SlugField | 只能包含字母,数字,下划线和连字符的字符串,通常被用于URLs表示 |
CommaSeparatedIntegerField | 以逗号间隔的整数序列,必须有max_length |
IntegerField | 整数[-2147483648,2147483647 ] |
PositiveIntegerField |
正整数[0 ,2147483647] |
PositiveSmallIntegerField | 正短整数[0 ,32767] |
SmallIntegerField | 小整数[-32768 ,32767] |
BigIntegerField | 64位的整型数值 (-2^63) – (2^63-1) |
BinaryField | 存储原始的2进制数据,功能有限,仅支持字节分配 |
Decimalfield | 十进制浮点数 , 参数maxdigits表示总位数, 参数decimalplaces表示小数位数 |
FloatField | 浮点数 |
DateField | 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 |
TimeField | 时间,参数同date |
DateTimeField | 日期时间,参数同date |
EmailField | 带有email合法性检测的一个CharField |
IPAddressField | 点分十进制表示的IP地址,如10.0.0.1 |
GenericIPAddressField | ip v4和ip v6地址表示,ipv6遵循RFC 4291section 2.2 |
FileField | 有一个必须参数upload_to,用于保存文件的本地文件系统 |
FilePathField |
一个CharField,用来选择文件系统下某个目录里面的某些文件,它有三个专有参数,只有path是必须的。path是一个目录的绝对路径,match是一个正则表达式字符串,用来过滤文件名称;recursive为bool,指定是否包含path下的子目录。 |
imageField | 继承于FileField,对上传的 内容进⾏行行校验,确保是有效的图⽚片(必须要安装Pillow才可以使用(pip install Pillow) |
ForeignKey |
外键,参数一链接的模型,参数二on_delte,级联删除,一般为
on_delete=models.CASCADE |
ManyToManyField |
多对多 add()添加 remove()移除 |
参数
null | 如果为True,表示允许为空,默认值是False |
blank | 如果为True,则该字段允许为空白,默认值是False |
db_column | 字段的名称,如果未指定,则使用属性的名称 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False |
default | 默认 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False |
模型方法
class HighRatingManager(models.Manager):def get_queryset(self):return super().get_queryset().filter(rating=1)# CHOICES选项
class Rating(models.IntegerChoices):VERYGOOD = 1, 'Very Good'GOOD = 2, 'Good'BAD = 3, 'Bad'class Product(models.Model):# 数据表字段name = models.CharField('name', max_length=30)rating = models.IntegerField(max_length=1, choices=Rating.choices)# MANAGERS方法objects = models.Manager()high_rating_products =HighRatingManager()# META类选项class Meta:abstract=True # 指定该模型为抽象模型,不会在数据库里创建数据表proxy=True # 指定该模型为代理模型,即克隆一个与模型A相同的模型Bverbose_name = 'product' # 为模型设置便于人类阅读的别名verbose_name_plural = 'products' # 为模型设置便于人类阅读的别名db_table= xxx # 自定义数据表名,属性为字符串odering=['-pub-date'] # 自定义按哪个字段排序,-代表逆序permissions=[] # 为模型自定义权限managed=False # 默认为True,如果为False,Django不会为这个模型生成数据表,即是否支持数据迁移命令indexes=[] # 为数据表设置索引,对于频繁查询的字段,建议设置索引constraints= # 给数据库中的数据表增加约束。# __str__方法def __str__(self):return self.name# 重写save方法def save(self, *args, **kwargs):do_something()super().save(*args, **kwargs) do_something_else()# 定义单个对象绝对路径def get_absolute_url(self):return reverse('product_details', kwargs={'pk': self.id})# 其它自定义方法def do_something(self):
示例
class UserInfo(models.Model):# 邮箱uname = models.EmailField()# 密码经加密后长度会变长pwd = models.CharField(max_length=60)class Meta:ordering = ('id',)class CartItem(models.Model):goodsid = models.PositiveIntegerField() colorid = models.PositiveIntegerField() sizeid = models.PositiveIntegerField() count = models.PositiveIntegerField() isdelete = models.BooleanField( default=False)user = models.ForeignKey(UserInfo,on_delete=models.CASCADE) #外键
增加
_obj = {'goodsid':goodsid,'colorid':colorid,'sizeid':sizeid,'count':count,'user':user
}
CartItem.objects.create(**_boj)
批量增加
a = [1,2,3]
arr = []
for i in a:arr.append(User(cid=i))
User.objects.bulk_create(arr)
删除
user=User.object.get(id=1)
user.delete()
users=User.objects.all()
users.delete()
更新
update只适用于filter查询结果
user.cartitem_set.filter(goodsid=goodsid,colorid=colorid,sizeid=sizeid
).update(count=count,isdelete=False)
单个结果用save
config.json = "hoge"
config.save()
更新或新增
book.objects.update_or_create(defaults={'name':'安尔达'},id=5)
# defaults中的内容为查询内容,后面的是需要更新的内容。
批量更新
querys = User.objects.all()
arr = []
for i in querys:if i.state == 3:o = User(id=i.id,type=3,sum_fans=0)if i.start == 4:o = User(id=i.id,type=4,sum_fans=2)else:o = User(id=i.id,type=5,sum_fans=5)arr.append(o)
User.objects.bulk_update(arr, ['type', 'sum_fans'])
查询
userList = UserInfo.objects.filter(uname=uname,pwd=pwd)
user = userList[0]cart = user.cartitem_set.filter(goodsid=goodsid,colorid=colorid,sizeid=sizeid)
cart.count() #查到的数量# order_by('id') 按id升序 / order_by('-id') 按id降序
user.cartitem_set.order_by('id').filter(isdelete=False).all()#根据goodsid,sizeid,colorid获取CartItem对象
user.cartitem_set.get(goodsid=goodsid,sizeid=sizeid,colorid=colorid)
get的参数只能是model中定义的哪些字段,只支持严格匹配
filter的参数可以是字段也可以是扩展的where查询关键字,如in,like
get返回值是一个定义的model对象
filter返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作,QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型(是一个object对象集合)
get只有一条记录返回的时候才正常,也就是说明get查询字段必须是主键或者唯一约束的字段。当返回多条记录或者没有找到记录的时候都会抛出异常
get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错,有多条记录也会报错。
filter有没有匹配的记录都可以
filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。
另外,从别的资料里看到filter好像有缓存数据的功能,第一次查询数据库并生成缓存,下次再调用filter方法的话,直接取得缓存的数据,会get方法每次执行都是直接查询数据库的,不知道这个是不是正确,看看就好。
模糊查询
1.查询某个字符串是否在指定的字段中
article1 = models.Article.objects.filter(id__contains=1) # 区分大小写
article2 = models.Article.objects.filter(id__icontains = 1) #不区分大小写
2.指定某个字段的是否在某个集合中
articles = models.Article.objects.filter(id__in=[1,2,3])
for article in articles:print(article)
3.大于、大于等于、小于、小于等于
gt、gte、lt、lte
articles = models.Article.objects.filter(id__gt=2)# 在 ... 之间,左闭右闭区间,= 号后面为两个元素的列表
articles = models.Article.objects.filter(id__range=[10,20])
4.某个值开始、以某个值结束
字段以指定字符开头与结尾
articles = Article.objects.filter(title__startwith="hello")
articles = Article.objects.filter(title__endswith="hello")
articles = Article.objects.filter(title__istartswith="hello") # 不区分大小写
articles = Article.objects.filter(title__iendswith="hello")import datetime
from django.utils.timezone import make_awarestart_time = make_aware(datetime(year=2018,month=11,day=2,hour=16,minute=0,second=0))
end_time = make_aware(datetime(year=2018,month=11,day=2,hour=17,minute=0,second=0))
articles = models.Article.objects.filter(create_time__range=(start_time,end_time))
print(articles)
print(articles.query)
5.date
articles = models.Article.objects.filter(create_time__date = datetime(year=2018,month=11,day=2))
print(articles.query)
print(articles)
然后添加映射,然后我们发现并没有查找出结果出来,但是我们是刚才添加的信息,时间也是设置为刚才的,为什么没有信息呢。
原因是因为MySQL默认是没有储存时区相关的信息,但是在执行sql语句时我们发现对时区进行了装换,所以时不会得到我们想要的结果的。因此我们需要下载一些时区表的文件,然后添加到mysql的配置路径中。
windows中
在http://dev.mysql.com/downloads/timezones.html下载timezone_2018d_posix.zip - POSIX standard。然后将下载下来的所有文件拷贝到C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql中,如果提示文件名重复,那么选择覆盖即可。
linux或者mac系统
在命令行中执行以下命令:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -D mysql -u root -p,然后输入密码,从系统中加载时区文件更新到mysql中。
然后对上面的代码不需要进行改动,也能执行成功了
6.year/month/day:根据年/月/日进行查找
articles = models.Article.objects.filter(create_time__year=2018)
articles = models.Article.objects.filter(pub_date__year__gte=2017)
7.week_day: 根据星期来进行查找
1表示星期天,7表示星期六,2-6代表的是星期一到星期五。比如要查找星期三的所有文章,那么可以通过以下代码来实现:
articles = models.Article.objects.filter(create_time__week_day=4)
8.time: 根据时间进行查找
如果要具体到秒,一般比较难匹配到,因为数据库中秒后面还有小数。可以使用区间的方式来进行查找。区间使用range
条件。比如想要获取17时/10分/27-28秒之间的文章,那么可以通过以下代码来实现:
from datetime import datetime,timestart_time = time(hour=17,minute=10,second=27)
end_time = time(hour=17,minute=10,second=28)
articles = models.Article.objects.filter(create_time__time__range=(start_time,end_time))
更多的关于时间的过滤,请参考Django官方文档:QuerySet API reference | Django documentation | Djangohttps://docs.djangoproject.com/en/2.1/ref/models/querysets/#range
9.isnull:根据值是否为空进行查找
# 查询title为空的
articles = models.Article.objects.filter(create_time__isnull=True)
# 查询title不为空的
articles = models.Article.objects.filter(create_time__isnull=False)
10.regex:正则表达式
articles = models.Article.objects.filter(title__regex=r"^三国")
articles = models.Article.objects.filter(title__iregex=r"^三国") # 不区分大小写
11.查找字段最大值
from django.db.models import Maxmax = User_company.objects.aggregate(Max('nid'),Max('id'))
# {'nid__max': 9, 'id__max': 70}
查询集合并
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')# 合并到一起
qs = qs1 | qs2 | qs3
查询方法
all() | 查询所有内容 |
get() | 查询符合条件的返回模型类的对象符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误 |
filter() | 查询符合条件的数据 |
exclude() | 查询不符合条件的数据 |
order_by() | 对查询结果进行排序 |
reverse() | 对查询结果进行反转 |
count() |
查询数据的数量返回的数据是整数 输入参数,则为统计该列非空数量。 |
first() | 返回第一条数据,返回的数据是模型类的对象也可以用索引下标 |
last() | 返回最后一条数据返回的数据是模型类的对象不能用索引下标 [-1],ORM 没有逆序索引 |
exists() | 判断查询的结果 QuerySet 列表里是否有数据 |
values() |
查询部分字段的数据 返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个可迭代的字典序列,字典里的键是字段,值是数据。 |
values_list() |
查询部分字段的数据 返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个个元组,元组里放的是查询字段对应的数据。 |
distinct() | 对数据进行去重 |
select_related() |
Goods.object.select_related('User').get(id=0) 同时查询外键,以减少多外键时的查询交数 |
only() |
Blog.objects.filter(category='django').only('author','title') 仅查询指定列,提高查询速度 |
defer() | 仅查询指定字段以外的列,提高查询速度 |
其他
模型类转字典
__dict__
>>> Group.objects.get(id=1).__dict__
{'id': 1, 'name': 'GroupA', '_state': <django.db.models.base.ModelState object at 0x7f68612daef0>}
# 有缺陷 多个没用的_state字段,外键字段有问题
model_to_dict
>>> model_to_dict(Group.objects.get(id=1))
{'name': 'GroupA', 'id': 1}
>>>
>>> model_to_dict(User.objects.get(id=2))
{'leader': 1, 'is_active': True, 'username': 'ops-coffee@163.com', 'fullname': '运维咖啡吧', 'group': [<Group: GroupA>, <Group: GroupC>, <Group: GroupE>], 'id': 2}
这种方法能满足大部分的需求,且输出也较为合理,同时还有两个参数fields
和exclude
来配置输出的字段,例如:
>>> from django.forms import model_to_dict
>>> model_to_dict(User.objects.get(id=2), fields=['fullname','is_active'])
{'is_active': True, 'fullname': '运维咖啡吧'}
>>>
>>> model_to_dict(User.objects.get(id=2), exclude=['group','leader','id'])
{'fullname': '运维咖啡吧', 'is_active': True, 'username': 'ops-coffee@163.com'}
模型类转JSON字符串
from django.core.serializers import serializejsondata = serialize('json',data)
模板
模板中 字典key为变量
from django.template.defaulttags import register@register.filter
def get_item(dictionary,key):return dictionary.get(key)
{% for item in pageObj %}<h7>{{ nameDict|get_item:item.cid }}</h7>
{% endfor %}
数据回滚
一、整体回滚
所有的数据库更新操作都会在一个事务中执行,如果事务中任何一个环节出现错误,都会回滚整个事务。
from django.db import transaction, DatabaseError# open a transaction
@transaction.atomic #装饰器格式
def func_views(request):do_something() a = A() #实例化数据库模型try:a.save()except DatabaseError:pass
此方案整个view都会在事务之中,所有对数据库的操作都是原子性的。
from django.db import transaction, DatabaseErrordef func_views(request):try:with transaction.atomic(): #上下文格式,可以在python代码的任何位置使用a = A()a.save()#raise DatabaseError #测试用,检测是否能捕捉错误except DatabaseError: # 自动回滚,不需要任何操作pass
此方案比较灵活,事务可以在代码中的任意地方开启,对于事务开启前的数据库操作是必定会执行的,事务开启后的数据库操作一旦出现错误就会回滚。
Django 模型操作相关推荐
- python Django 模型操作
python Django 模型操作 1. 添加模型到数据库 2. objects:查找数据 3. all:查找所有数据 4. filter:数据过滤 5. get:获取单个对象 6. order_b ...
- Django中models模型(操作数据库)
ORM 自己创建数据库 连接数据库 Django操作表 数据库操作 新建 删除 获取数据 实例:用户管理 Django开发操作数据库更简单,内部提供了ORM框架 ORM的流程 ORM ORM,全称 O ...
- django orm原理_django 动态创建一个模型的多个table name, 并通过 Django ORM 操作
动态创建table, 并通过 Django ORM 操作. 动态的创建表 动态的创建模型其实就是在运行时生成 Model 类, 这个可以通过函数实现, 通过传参(今天的日期, 如: 20181211) ...
- Django项目实践3 - Django模型(字段、数据库操作及模型继承)
http://blog.csdn.net/pipisorry/article/details/45725953 Django数据库字段类型(Field types) AutoField class A ...
- Django基础五之Django模型层(二)多表操作
Django基础五之Django模型层(二)多表操作 一 创建模型 表和表之间的关系 一对一.多对一.多对多 # 作者表 比较常用的信息放在这个表中 class Author(models.Model ...
- 4Python全栈之路系列之Django模型
Python全栈之路系列之Django模型 MTV开发模式 把数据存取逻辑.业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的Model-View-Controller(MVC)模式.在这个模式中 ...
- Web开发-Django模型层
Django模型层 简述 Django框架处理业务的逻辑一般如下(省略图,源于网络,侵删) 可以看到,Django自带了一套ORM机制,这也是Django框架的核心-"全面",将一 ...
- Django模型(三)
Django模型(三) 文章目录 Django模型(三) 一.模型类关系 1.关系字段类型 2.一对多关系 3.多对多关系 二.关联查询 1.通过对象执行关联查询 2.通过模型类执行关联查询 三.自关 ...
- Django模型(二)
Django模型(二) 文章目录 Django模型(二) 一.字段查询 1.查看mysql数据库日志 二.条件运算符 1.查询等 2.模糊查询 3.空查询 4. 范围查询 5. 比较查询 6).日期查 ...
最新文章
- ZStack--通过Ansible实现全自动化
- 【Python学习笔记】面向对象三大特性
- TypeError: 'module' object is not callable 原因分析(python模块导入注意事项)
- 【面试招聘】阿里、腾讯 | 算法岗面试复盘
- mac 系统使用macaca inspector 获取iphone真机应用元素
- 安卓工业平板电脑的蓝牙开发教程
- java 消费者模式 多线程_[Java并发-24-并发设计模式] 生产者-消费者模式,并发提高效率...
- 带你换个角度理解图卷积网络
- javaWeb注册,登陆,注销功能的实现
- 百度地图和solr展示资源和附近等功能的实现 二
- SPI总线接口与简单配置
- 学习总结-《父与子的编程之旅》chapter 17
- java正则表达式或_java 正则表达式
- spoj4487(splay)
- 设置笔记本电脑插入USB鼠标时,自动禁用触摸板
- matlab 中偏微分符号,一阶、二阶偏微分方程符号运算
- 来自#Devoxx 2014的WebSocket螺母和螺栓的幻灯片
- android 账号同步功能吗,android账号管理与同步机制
- Android内存原理
- 储存过程的优点?缺点?
热门文章
- 怎么做表情包微信gif?好用的制作方法介绍
- SwiftUI学习记录
- 使用k-d树进行无序点云去噪
- 阿里面试,问了我乐观锁、悲观锁、AQS、sync和Lock,这个回答让我拿了offer
- python zipfile压缩的文件用shell命令解压_Python学习第177课——bzip2、zip方式压缩文件和解压文件...
- shui jisfnemskddp psijsjfsif
- JAVA采用S7通信协议访问西门子PLC
- 寂静和静寂_静寂的意思
- 巫师3储物箱在哪_巫师3全宝藏宝箱地图分享 各种宝藏的具体位置
- 自学大数据可以找到工作吗?该怎么学?