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服务器拒绝服务攻击代码
Jan 16 Python
python益智游戏计算汉诺塔问题示例
Mar 05 Python
Python实现批量读取word中表格信息的方法
Jul 30 Python
理解python正则表达式
Jan 15 Python
python中日志logging模块的性能及多进程详解
Jul 18 Python
python生成lmdb格式的文件实例
Nov 08 Python
Python多线程应用于自动化测试操作示例
Dec 06 Python
Python实现字符串匹配的KMP算法
Apr 04 Python
Tensorflow设置显存自适应,显存比例的操作
Feb 03 Python
Python中os模块功能与用法详解
Feb 26 Python
python实现吃苹果小游戏
Mar 21 Python
python 实现的截屏工具
May 08 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
Email+URL的判断和自动转换函数
2006/10/09 PHP
JS实现php的伪分页
2008/05/25 PHP
php连接数据库代码应用分析
2011/05/29 PHP
遍历指定目录,并存储目录内所有文件属性信息的php代码
2016/10/28 PHP
php语言注释,单行注释和多行注释
2018/01/21 PHP
Javascript 实用小技巧
2010/04/07 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
2012/05/23 Javascript
js生成随机数之random函数随机示例
2013/12/20 Javascript
每天一篇javascript学习小结(RegExp对象)
2015/11/17 Javascript
使用JavaScript判断手机浏览器是横屏还是竖屏问题
2016/08/02 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
2018/10/08 Javascript
layui表格分页 记录勾选的实例
2019/09/02 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
解决VUE-Router 同一页面第二次进入不刷新的问题
2020/07/22 Javascript
python实现在每个独立进程中运行一个函数的方法
2015/04/23 Python
Python生成器generator用法示例
2018/08/10 Python
Python 二叉树的层序建立与三种遍历实现详解
2019/07/29 Python
python实现网站用户名密码自动登录功能
2019/08/09 Python
python manage.py runserver流程解析
2019/11/08 Python
Python生成个性签名图片获取GUI过程解析
2019/12/16 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
详解python安装matplotlib库三种失败情况
2020/07/28 Python
Python实现数字的格式化输出
2020/08/01 Python
Java基础知识面试要点
2016/07/29 面试题
为什么要做架构设计
2015/07/08 面试题
工商管理专业学生的自我评价
2013/10/01 职场文书
协议书格式
2014/04/23 职场文书
学校食品安全实施方案
2014/06/14 职场文书
出纳岗位职责范本
2015/03/31 职场文书
2015法院个人工作总结范文
2015/05/25 职场文书
2019年销售部季度工作计划3篇
2019/10/09 职场文书
PHP实现考试倒计时功能代码
2021/04/16 PHP
使用nginx配置访问wgcloud的方法
2021/06/26 Servers
python基础之错误和异常处理
2021/10/24 Python
十大最强妖精系宝可梦,哲尔尼亚斯实力最强,第五被称为大力士
2022/03/18 日漫