Django中Model的使用方法教程


Posted in Python onMarch 07, 2018

前言

本文主要给大家介绍了关于Django中Model使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

创建模型

使用Django的模型主要注意两个方面:字段的类型和方法的重写。这里用一个例子来说明,其中包含了常用的字段类型和如何重写方法。

from django.db import models
class School(models.Model):
 pass
class Message(models.Model):
 pass
class Teacher(models.Model):
 pass
 class Student(models.Model):
 GENDER_CHOICES = (
  ('male', "男"),
  ('female', "女"),
  ('secret', "保密")
 )

 name = models.CharField(max_length=40, blank=True, verbose_name="姓名")
 gender = models.CharField(max_length=6, choices=GENDER_CHOICES, default="secret", verbose_name="性别")
 age = models.IntegerField(default=0, verbose_name="年龄")
 rank = models.PositiveIntegerField(default=1, verbose_name="排名", unique=True)
 discount = models.DecimalField(max_digits=3, decimal_places=2, verbose_name="折扣", default=1.0)
 school = models.ForeignKey(to=School, verbose_name="学校", on_delete=models.CASCADE)
 message = models.OneToOneField(to=Message, verbose_name="信息", on_delete=models.CASCADE)
 teacher = models.ManyToManyField(verbose_name="老师", to=Teacher, blank=True)
 introduce = models.TextField(blank=True, verbose_name="介绍")
 grade = models.FloatField(default=0.0, verbose_name="成绩")
 url = models.URLField(verbose_name="个人主页", max_length=100)
 email = models.EmailField(verbose_name="邮箱")
 image = models.ImageField(upload_to='img/%Y/%m/%d/', verbose_name='上传图片', null=True)
 file = models.FileField(upload_to="file/%Y/%m/%d/", verbose_name="上传文件", blank=True)
 is_deleted = models.BooleanField(verbose_name="已删除", default=False, blank=True)
 time_added = models.DateTimeField(verbose_name="添加时间", auto_now_add=True, blank=True)
 def delete(self, using=None, keep_parents=False):
  self.is_deleted = True
  # some actions
  self.save()
 def save(self, force_insert=False, force_update=False, using=None,
    update_fields=None):
  # some actions
  self.name = self.name.capitalize() # 首字母大写
  return super().save(force_insert=force_insert, force_update=force_update, using=using,
       update_fields=update_fields)
 def __repr__(self):
  return "UserProfile:{}".format(self.name)
 def __str__(self):
  return self.name
 class Meta:
  ordering = ['-time_added']
  verbose_name = "用户信息"
  verbose_name_plural = verbose_name
  db_table = "student_info"

字段类型

这里对常见字段中值得注意的地方作一下说明。

CharField

字符串类型值得注意的是当该字段只能在是某些指定的值时,要使用choices参数来指向预先设定的值。

IntergerField & PositiveIntegerField

整数类型和正整数类型。

DecimalField

十进制浮点数,其中,参数max_digits代表数字有多少位,decimal_places代表小数部分有多少位。

ForeignKey

使用to指向被关联的模型,使用on_delete来规定被关联对象删除时该对象的处理方式。主要有两种取值,models.CASCADE和models.SET_NULL。models.CASCADE表示当被关联对象删除时删除该对象,models.SET_NULL表示当被关联对象被删除时将该对象设置为空,此设置的前提是该字段要允许为空。

ImageField & FileField

使用upload_to参数来指定文件保存的路径。注意,该路径前面再加上 MEDIA_ROOT中设置的路径就是上传的文件真实保存路径了,如 MEDIA_ROOT的路径是'/home/media',那图片上传的路径就类似/home/media/img/2018/03/06。

BooleanField

布尔类型,可以使用default指定默认值。

DateTimeField

在Django中,代表时间字段的有三种:DateTimeField、DateField、TimeField,三种类型分别对应datetime()、date()、time(),都有auto_now和auto_now_add参数。

  • auto_now
    默认值为False,设置为True时会在每次修改该对象时自动更新为当前时间,但是无法手动修改该字段的值。
  • auto_now_add
    默认值为False,设置为True时会在创建对象时自动设置为当前时间,之后都不再修改,也不能手动修改其值。
  • 默认当前时间,又能修改
    有时候我们需要在创建对象时设置字段的值为当前时间,在后续时又能修改,使用auto_now或者auto_now_add都无法实现这一点。此时,可以使用default参数来设置默认值,如下
from django.db import models
from django.utils import timezone
class Message(models.Model):
add_date = models.DateTimeField(verbose_name='保存日期',default = timezone.now)
mod_date = models.DateTimeField(verbose_name='最后修改日期', auto_now = True)

重写方法

delete

Django默认的删除是将数据从数据库里删除,有时候我们需要软删除,保存以前的数据,这时候我们可以使用一个布尔类型的字段标识该条数据是否删除,这时需要重写delete方法实现软删除。

在delete方法中将is_deleted的值设置为True,表示该条数据已删除。此外还可以执行一些关联的动作,比如对相关字段赋值等,最后保存对象。

save

重写save方法可以让我们在保存数据时做一些相关的操作,比如保存姓名时自动设置为首字母大写,执行完之后需要调用父类的save方法进行保存。

repr & str

两者的作用是将变量或者常量转换为字符串对象,这里重写该方法使得对象实例能被转化为字符串。

class Meta

  • ordering:结果集按照何种方式排序,上面例子表示按添加时间的逆序排序
  • verbose_name:对象的名称
  • verbose_name_plural:对象复数形式的名称
  • db_table:在数据库中的表名

常用方法

在对常用方法介绍部分,由于上面的模型包含字段较多,所以不使用上面创建的模型。这里使用一些常见的模型,通过名字就可以知道代表的内容,因此就不列出模型了。

创建实例

create

使用create方法可以创建一个模型实例,将各字段在参数中设置各个字段的值。

student = Student.objects.create(name='zhangsan', gender='male')

get_or_create

get_or_create的作用是查询一个实例,当实例不存在时则创建一个实例。

obj, created = Person.objects.get_or_create(
 first_name='John',
 last_name='Lennon',
 defaults={'birthday': date(1940, 10, 9)},
)

函数返回一个(object, created)的tuple,object是查询或者创建的对象实例,created是个布尔类型的值,表示是否是新创建的实例。在查询时使用defaults以外的参数进行查询,当实例不存在时将包含default参数一起创建一个新的实例。功能类似于如下代码:

try:
 obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
 obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
 obj.save()

update_or_create

update_or_create的作用是更新一个实例,当实力不存在时则创建一个实例。

obj, created = Person.objects.update_or_create(
 first_name='John', last_name='Lennon',
 defaults={'first_name': 'Bob'},
)

函数返回一个(object, created)的tuple,object是更新或者创建的对象实例,created是个布尔类型的值,表示是否是新创建的实例。在查询的对象实例存在时,使用default中的参数进行更新,当实例不存在时,创建新的对象实例,需要更新的字段的值设置为default中的值。功能类似:

defaults = {'first_name': 'Bob'}
try:
 obj = Person.objects.get(first_name='John', last_name='Lennon')
 for key, value in defaults.items():
  setattr(obj, key, value)
 obj.save()
except Person.DoesNotExist:
 new_values = {'first_name': 'John', 'last_name': 'Lennon'}
 new_values.update(defaults)
 obj = Person(**new_values)
 obj.save()

add

这里补充一下add方法,add用在多对多的关系模型上,表示添加该字段的指向对象。

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

上面的Author表示作者模型,entry表示书籍条目,一本书可以有多个作者,采用多对多关系。add可以为书的实例添加多个作者。

查询

all

all方法查询该对象的所有实例。

all_entries = Entry.objects.all()

get

使用get查询实例,当实例不存在时会返回一个不存在异常。

>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")

filter

filter返回一个QuerySet,而不是对象实例,当查询结果不存在时返回空的QuerySet,而不是返回一场,可以对结果集作切片操作来获取实例内容。下面代码功能在有对象实例时等同于上面get的操作。

>>> entry = Entry.objects.filter(pk=1)[0]
>>> cheese_blog = Blog.objects.filter(name="Cheddar Talk")[0]

filter结果可以链式地进行操作,也就是后面可以接多个过滤条件。

Entry.objects.filter(pub_date__year=2006)
Entry.objects.all().filter(pub_date__year=2006)
Entry.objects.filter(blog__name__year="zhangsan")

上面的pub_date__year表示取出DateField类型的pub_date的年,类似的可以取出月__month,日__day。在使用外键ForeignKey时可以使用双下划线来表示被关联对象的字段。

现在来看一下链式过滤的例子。

Entry.objects.filter(
...  headline__startswith='What'
... ).exclude(
...  pub_date__gte=datetime.date.today()
... ).filter(
...  pub_date__gte=datetime.date(2005, 1, 30)
... )

首先使用__startswith过滤标题以'What'开始的数据。然后保留让发布日期小于今天的数据,exclude表示排除条件内的那部分数据,条件使用了__gte表示大于当前日期,该部分过滤类似于filter后面使用__lte小于。最后也是使用__gte大于一个自定义的日期。

除了上面的过滤条件外,常见的还有__icontains,表示包含该内容。

Q

Q是Django自带的内容,用于查询。主要的用途是在页面的搜索框中输入内容后台查询相应的数据集。

student = student.filter(Q(name__icontains=search) |
       Q(teacher__name__icontains=search) |
       Q(gender__icontains=search) |
       Q(url__icontains=search))

上述例子常用在一个搜索框可能搜索多个字段的内容时,各个过滤条件之间使用“|”进行或者运算。当多条件查询时,各个条件是并运算,使用“&”代替“|”。

Q可以复制给个变量,有时候我们需要对Q后面的内容先做一些处理,如将日期拼凑出来等,这时候可以先把Q赋值给一个变量,然后对变量进行“|”或者“&”操作。

query = Q(name__icontains=search)
query = query | Q(teacher__name__icontains=search)
student = student.filter(query)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python 爬虫学习笔记之多线程爬虫
Sep 21 Python
Python学习小技巧之利用字典的默认行为
May 20 Python
Python3对称加密算法AES、DES3实例详解
Dec 06 Python
使用python将excel数据导入数据库过程详解
Aug 27 Python
springboot配置文件抽离 git管理统 配置中心详解
Sep 02 Python
pytorch实现onehot编码转为普通label标签
Jan 02 Python
Python函数默认参数常见问题及解决方案
Mar 26 Python
python 异步async库的使用说明
May 04 Python
使用Python实现批量ping操作方法
May 06 Python
如何利用python生成MD5并去重
Dec 07 Python
python3.9和pycharm的安装教程并创建简单项目的步骤
Feb 03 Python
pytorch 运行一段时间后出现GPU OOM的问题
Jun 02 Python
python使用opencv按一定间隔截取视频帧
Mar 06 #Python
python+ffmpeg视频并发直播压力测试
Mar 06 #Python
小白如何入门Python? 制作一个网站为例
Mar 06 #Python
python调用系统ffmpeg实现视频截图、http发送
Mar 06 #Python
Python从零开始创建区块链
Mar 06 #Python
Django 实现下载文件功能的示例
Mar 06 #Python
python入门前的第一课 python怎样入门
Mar 06 #Python
You might like
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
php堆排序实现原理与应用方法
2015/01/03 PHP
php修改上传图片尺寸的方法
2015/04/14 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
THINKPHP3.2使用soap连接webservice的解决方法
2017/12/13 PHP
关于ThinkPHP中的异常处理详解
2018/05/11 PHP
ThinkPHP5.0框架实现切换数据库的方法分析
2019/10/30 PHP
[JS源码]超长文章自动分页(客户端版)
2007/01/09 Javascript
原生javascript和jquery判断浏览器版本等信息
2013/07/04 Javascript
jQuery 绑定事件到动态创建的元素上的方法实例
2013/08/18 Javascript
javascript中Function类型详解
2015/04/28 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
2015/05/09 Javascript
基于JavaScript操作DOM常用的API小结
2015/12/01 Javascript
JavaScript File API实现文件上传预览
2016/02/02 Javascript
Webpack执行命令参数详解
2017/06/17 Javascript
js 索引下标之li集合绑定点击事件
2018/01/12 Javascript
浅谈AngularJS中$http服务的简单用法
2018/05/15 Javascript
JavaScript解析机制与闭包原理实例详解
2019/03/08 Javascript
NodeJs之word文件生成与解析的实现代码
2019/04/01 NodeJs
用原生 JS 实现 innerHTML 功能实例详解
2019/04/03 Javascript
Vue实现开心消消乐游戏算法
2019/10/22 Javascript
SpringBoot+Vue 前后端合并部署的配置方法
2020/12/30 Vue.js
[03:09]DOTA2亚洲邀请赛 LGD战队出场宣传片
2015/02/07 DOTA
[03:53]2016国际邀请赛中国区预选赛第三日TOP10精彩集锦
2016/06/29 DOTA
跟老齐学Python之使用Python操作数据库(1)
2014/11/25 Python
python获取远程图片大小和尺寸的方法
2015/03/26 Python
Python中格式化format()方法详解
2017/04/01 Python
Python高级用法总结
2018/05/26 Python
pandas带有重复索引操作方法
2018/06/08 Python
Django使用 Bootstrap 样式修改书籍列表过程解析
2019/08/09 Python
农村党支部先进事迹
2014/01/14 职场文书
住院医师规范化培训实施方案
2014/06/12 职场文书
房屋租赁合同解除协议书
2014/10/11 职场文书
论语读书笔记
2015/06/26 职场文书
英语导游欢迎词
2015/09/30 职场文书
css3带你实现3D转换效果
2022/02/24 HTML / CSS