精选文章 Model操作数据库详解(Django)

Model操作数据库详解(Django)

作者:ldq_sd 时间: 2020-07-27 09:23:34
ldq_sd 2020-07-27 09:23:34

一、django ORM简介

O(objects):类和对象。R(Relation):关系,关系数据库中的表格。M(Mapping):映射。

Django ORM框架的功能:

  1. 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。
  2. 根据设计的模型类生成数据库中的表格。
  3. 通过方便的配置就可以进行数据库的切换。

二、 数据库的配置

Django可以配置使用sqlite3,mysql,oracle,postgresql等数据库。Django默认使用的是sqlite3数据库,settigs.py里面:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',#默认使用的数据库引擎是sqlite3,项目自动创建
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),#指定数据库所在的路径
    }
}

Django项目也可以配置使用mysql数据库,使用如下配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',#表示使用的是mysql数据库的引擎
        'NAME': 'db1',      #数据库的名字,可以在mysql的提示符下先创建好
        'USER':'root',      #数据库用户名
        'PASSWORD':'',      #数据库密码
        'HOST':'',          #数据库主机,留空默认为"localhost"
        'PORT':'3306',      #数据库使用的端口
    }
}

配置好数据库的信息后还必须安装数据库的驱动程序,Django默认导入的mysql的驱动程序是MySQLdb,然而MySQLdb对于py3支持不全,所以这里使用PyMySQL。

pip install pymysql

在项目名文件下的__init__.py文件中写入如下配置:

import pymysql
pymysql.install_as_MySQLdb()

三、创建数据库表结构文件

对应app目录下的models.py

1、生成一个简单的数据库表:

在未指定primary_key的情况下,Django会默认创建一个id自增字段作为主键。

from django.db import models
 
class Account(models.Model):
    account_name = models.CharField(max_length=20)
    account_id = models.IntegerField(primary_key=True)
    balance = models.DecimalField(max_digits=2, decimal_places=2)

2、执行命令生成到数据库

python manage.py makemigrations 
python manage.py migrate # 生成数据表

四、数据库字段

AutoField(Field)	- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)	- bigint自增列,必须填入参数 primary_key=True
SmallIntegerField(IntegerField):	- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)	- 正小整数 0 ~ 32767
IntegerField(Field)	- 整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)	- 正整数 0 ~ 2147483647
BigIntegerField(IntegerField):	- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
BooleanField(Field)	- 布尔值类型
NullBooleanField(Field):	- 可以为空的布尔值
CharField(Field)	- 字符类型
	- 必须提供max_length参数, max_length表示字符长度
TextField(Field)	- 文本类型
EmailField(CharField):	- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)	- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)	- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
	- 参数:
		protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
		unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
URLField(CharField)	- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)	- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)	- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)	- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)	- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
	- 参数:
			path,                      文件夹路径
			match=None,                正则匹配
			recursive=False,           递归下面的文件夹
			allow_files=True,          允许文件
			allow_folders=False,       允许文件夹
FileField(Field)	- 字符串,路径保存在数据库,文件上传到指定目录
	- 参数:
		upload_to = ""      上传文件的保存路径
		storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)	- 字符串,路径保存在数据库,文件上传到指定目录
	- 参数:
		upload_to = ""      上传文件的保存路径
		storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
		width_field=None,   上传图片的高度保存的数据库字段名(字符串)
		height_field=None   上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)	- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)	- 日期格式      YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)	- 时间格式      HH:MM[:ss[.uuuuuu]]
DurationField(Field)	- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)	- 浮点型
DecimalField(Field)	- 10进制小数
	- 参数:
		max_digits,小数总长度
		decimal_places,小数位长度
BinaryField(Field)- 二进制类型

五、数据库字段参数

null                数据库中字段是否可以为空
db_column           数据库中字段的列名
default             数据库中字段的默认值
primary_key         数据库中字段是否为主键
db_index            数据库中字段是否可以建立索引
unique              数据库中字段是否可以建立唯一索引
unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
verbose_name        Admin中显示的字段名称
blank               Admin中是否允许用户输入为空
editable            Admin中是否可以编辑
help_text           Admin中该字段的提示信息
choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
					如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
					字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
					如:{'null': "不能为空.", 'invalid': '格式错误'}
validators          自定义错误验证(列表类型),从而定制想要的验证规则
					from django.core.validators import RegexValidator
					from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
					MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
					如:
						test = models.CharField(
							max_length=32,
							error_messages={
								'c1': '优先错信息1',
								'c2': '优先错信息2',
								'c3': '优先错信息3',
							},
							validators=[
								RegexValidator(regex='root_\d+', message='错误了', code='c1'),
								RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
								EmailValidator(message='又错误了', code='c3'), ]
   
				 )

六、数据库Meta元信息

class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"
            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]
 
            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)
 
            # admin中显示的表名称
            verbose_name
 
            # verbose_name加s
            verbose_name_plural

七、关系字段

关系字段用于保存数据表之间的关系,包括ForeignKey, ManyToManyField等。

1、ForeignKey

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要进行关联的表名
        to_field=None,              # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                                        - models.CASCADE,删除关联数据,与之关联也删除
                                        - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                                        - models.PROTECT,删除关联数据,引发错误ProtectedError
                                        - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                                        - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                                        - models.SET,删除关联数据,
                                                      a. 与之关联的值设置为指定值,设置:models.SET(值)
                                                      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
 
                                                        def func():
                                                            return 10
 
                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}
 
                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据

2、OneToOneField

OneToOneField(ForeignKey)
        to,                         # 要进行关联的表名
        to_field=None               # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
 
                                    ###### 对于一对一 ######
                                    # 1. 一对一其实就是 一对多 + 唯一索引
                                    # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                    # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)
 
                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

3、ManyToManyField

ManyToManyField(RelatedField)
        to,                         # 要进行关联的表名
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}
 
                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                    # 做如下操作时,不同的symmetrical会有不同的可选字段
                                        models.BB.objects.filter(...)
 
                                        # 可选字段有:code, id, m1
                                            class BB(models.Model):
 
                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=True)
 
                                        # 可选字段有: bb, code, id, m1
                                            class BB(models.Model):
 
                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=False)
 
        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                        from django.db import models
 
                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)
 
                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through='Membership',
                                                through_fields=('group', 'person'),
                                            )
 
                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称

八、数据库基本操作

​#创建一个书的类,继承models类
class Book(models.Model):
 
    #用models类创建书的名字,类型为字符串,CharField相当于mysql语句中的varchar,字段最长为32
    title = models.CharField(max_length=32)
    
    #创建书的价格,类型为浮点型,小数点前最长4位,小数点后最长2位
    price = models.DecimalField(max_digits=6, decimal_places=2)
    
    #创建书的出版社信息,其与出版社的外键关系为一对多,所以用外键
    publish = models.ForeignKey(Publish)
    
    #创建书的出版日期,类型为日期
    publication_date = models.DateField()
    
    #创建书的类型信息,为字符串类型,最长为20
    classification=models.CharField(max_length=20)
    
    #创建书的作者信息,书籍与作者的关系为多对多,所以使用many-to-many
    authors = models.ManyToManyField("Author")
​

1、增

1.1一对一信息的创建

a、使用create方式

方式一: Publish.objects.create("name"="人民出版社",city="北京"}

方式二: Publish.objects.create(**{"name":"文艺出版社","city":"上海"}}

b、使用save方式

方式一:

book1=Book(title="python",price="88",publish_id="1",publication_date="2017-06-18")

book1.save()

方式二:

author1=Author(name="jerry")

author1.save()

1.2一对多的信息的创建(Foreignkey)

方式一:

#获取出版社对象
publish_obj=Publish.objects.get(id=4)   
 
#将出版社的对象绑定到书籍的记录中
Book.objects.create(
    title="python",
    price=48.00,
    publication_date="2017-07-12",
    publish=publish_obj,
)   

方式二:

#直接把出版社的id号插入到书籍的记录中
Book.objects.create(
    title="python",
    price=48.00,
    publish_id=2,
    publication_date="2017-06-18",
)

1.3多对多信息的创建(ManyToManyField())

a、为一本书添加多个作者

author1=Author.objects.get(id=1)#获取id号为1的作者对象
author2=Author.objects.filter(name="tom")#获取名字为"tom"的作者对象
book1=Book.objects.get(id=2)#获取id号为2的书籍对象
book1.authors.add(author1,author2)#为书籍对象添加多个作者对象

也可以用这种方式:

book1.authors.add(*[author1,author2])#为书籍对象添加作者对象的列表
book1.authors.remove(*[author1,author2])#删除指定书籍的所有作者

b、为一个作者添加多本书

author_obj = Author.objects.filter(name="jerry")#获取名字为"jerry"的作者对象
book_obj=Book.objects.filter(id__gt=3)#获取id大于3的书籍对象集合
author_obj.book_set.add(*book_obj)#为作者对象添加书籍对象集合
author_obj.book_set.remove(*book_obj)#删除指定作者对象所有的书籍

使用models.ManyToManyField()会自动创建第三张表

1.4手动创建多对多的作者与书籍信息表

class Book2Author(models.Models):
    author=models.ForeignKey("Author")#为作者指定Author这张表做为外键
    book=models.ForeignKey("Book")#为书籍指定Book这张表做为外键
 
author_obj=models.Author.objects.filter(id=3)[0]#获取Author表中id为3的作者对象
book_obj=models.Book.objects.filter(id=4)[0]#获取Book表中id为4的书籍对象

方式一:

obj1=Book2Author.objects.create(author=author_obj,book=book_obj)
obj1.save()

方式二:

obj2=Book2Author(author=author_obj,book=book_obj)
obj2.save()

2、删

Book.objects.filter(id=1).delete()

3、改

3.1使用save方法将所有属性重新设定一遍,效率低

author1=Author.objects.get(id=3)#获取id为3的作者对象

author1.name="jobs"#修改作者对象的名字

author1.save()#把更改写入数据库

3.2使用update方法直接设置对就的属性

Publish.objects.filter(id=2).update(name="北京出版社")

注意:update()是QuerySet对象的一个方法,get返回的是一个model对象,其没有update方法.

filter返回的是一个QuerySet对象,filter里可以设定多个过滤条件

4、查

查询数据使用QuerySet API。 QuerySet是惰性执行的,创建Query Set不会访问数据库,只有在访问具体查询结果的时候才会访问数据库。

4.1查询方法:

filter(**kwargs)            包含了与所给筛选条件相匹配的对象
all()                       查询所有结果
get(**kwargs)               返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都是报错
values(*field)              返回一个ValueQuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
exclude(**kwargs)           包含了与所给的筛选条件不匹配的对象
order by(*field)            对查询结果排序
reverse()                   对查询结果反向排序
distinct()                  从返回结果中剔除重复记录
values_list(*field)         与values()非常相似,返回一个元组序列,values返回一个字典序列
count()                     返回数据库中匹配的记录的数量
first()                     返回数据库中匹配的对象的第一个对象
last()                      返回数据库中匹配的对象的最后一个对象
exists()                    判断一个对象集合中是否包含指定对象,包含返回True,不包含返回False
exclude()            排除满足条件的对象
annotate()            使用聚合函数
dates()                根据日期获取查询集
datetimes()            根据时间获取查询集
none()                创建空的查询集
union()                并集
intersection()        交集
difference()        差集
select_related()    附带查询关联对象
prefetch_related()    预先查询
extra()                附加SQL查询
defer()                不加载指定字段
only()                只加载指定的字段
using()                选择数据库
select_for_update()    锁住选择的对象,直到事务结束。
raw()                接收一个原始的SQL查询

1.filter():

filter(**kwargs)

返回满足查询参数的对象集合。

查找的参数(**kwargs)应该满足下文字段查找中的格式。多个参数之间是和AND的关系。

Student.objects.filter(age__lt=10)#查询满足年龄小于10岁的所有学生对象

2.exclude()

exclude(**kwargs)

返回一个新的QuerySet,它包含不满足给定的查找参数的对象

Student.objects.exclude(age__gt=20, name='lin')#排除所有年龄大于20岁且名字为“lin”的学员集

3.annotate():

nnotate(args, *kwargs)

使用提供的聚合表达式查询对象。

表达式可以是简单的值、对模型(或任何关联模型)上的字段的引用或者聚合表达式(平均值、总和等)。

annotate()的每个参数都是一个annotation,它将添加到返回的QuerySet每个对象中。

关键字参数指定的Annotation将使用关键字作为Annotation 的别名。 匿名参数的别名将基于聚合函数的名称和模型的字段生成。 只有引用单个字段的聚合表达式才可以使用匿名参数。 其它所有形式都必须用关键字参数。

例如,如果正在操作一个Blog列表,你可能想知道每个Blog有多少Entry:

>>> from django.db.models import Count

>>> q = Blog.objects.annotate(Count('entry'))

# The name of the first blog

>>> q[0].name

'Blogasaurus'

# The number of entries on the first blog

>>> q[0].entry__count

42

4.order_by():

order_by(*fields)

默认情况下,根据模型的Meta类中的ordering属性对QuerySet中的对象进行排序

Student.objects.filter(school="阳关小学").order_by('-age', 'name')

上面的结果将按照age降序排序,然后再按照name升序排序。"-age"前面的负号表示降序顺序。 升序是默认的。 要随机排序,使用"?",如下所示:

Student.objects.order_by('?')

5. reverse():

reverse()

反向排序QuerySet中返回的元素。 第二次调用reverse()将恢复到原有的排序。

如要获取QuerySet中最后五个元素,可以这样做:

my_queryset.reverse()[:5]

这与Python直接使用负索引有点不一样。 Django不支持负索引。

6.distinct():

distinct(*fields)

去除查询结果中重复的行。

默认情况下,QuerySet不会去除重复的行。当查询跨越多张表的数据时,QuerySet可能得到重复的结果,这时候可以使用distinct()进行去重。

7. values():

values(fields, *expressions)

返回一个包含数据的字典的queryset,而不是模型实例。

每个字典表示一个对象,键对应于模型对象的属性名称。如:

# 列表中包含的是Student对象

>>> Student.objects.filter(name__startswith='Lin')

]>

# 列表中包含的是数据字典

>>> Student.objects.filter(name__startswith='Lin').values()

另外该方法接收可选的位置参数*fields,它指定values()应该限制哪些字段。如果指定字段,每个字典将只包含指定的字段的键/值。如果没有指定字段,每个字典将包含数据库表中所有字段的键和值。如下:

>>> Student.objects.filter(name__startswith='Lin').values()

>>> Blog.objects.values('id', 'name')

8.values_list():

values_list(*fields, flat=False)

与values()类似,只是在迭代时返回的是元组而不是字典。每个元组包含传递给values_list()调用的相应字段或表达式的值,因此第一个项目是第一个字段等。 像这样:

>>> Student.objects.values_list('id', 'name')

获取数据表的全部数据记录:

Account.objects.all()

返回值可以进行切片,但不支持负索引。或者使用:

Account.objects.get(field_name=val)

示例:

Account.objects.get(account_name='john')

或者使用过滤器查询多条记录:

Account.objects.filter(accounnt_name=val)

严格等于

Account.objects.filter(account_name__iexact=val)

忽略大小写

Account.objects.filter(account_name__contains=val)

名称中包含val

Account.objects.filter(account_name__icontains=val)

忽略大小写,包含

Account.objects.filter(account_name__regex=val)

正则表达式

Account.objects.filter(account_name__iregex=val)

正则表达式,忽略大小写

与filter相反exclude用于返回不满足条件的查询结果。

Account.objects.exclude(account_name__contains=val)

filter与exclude可以进行链式查询

Account.objects.exclude(account_name__contains='john').exlucde(balance=0)

对于查询结果可以使用distinct()去重或者使用order_by(field)进行排序。

Account.objects.filter(account_name__regex=val).distinct()

Account.objects.filter(account_name__regex=val).oreder_by('balance')

使用reverse()方法可以反转结果集中的元素顺序,调用两次将会恢复原顺序。

从SQL 的角度,QuerySet和SELECT 语句等价,过滤器是像WHERE 和LIMIT 一样的限制子句。

like:
 
    __exact        精确等于       like 'aaa'
    __iexact       精确等于       忽略大小写 ilike 'aaa'
    __contains     包含           like '%aaa%'
    __icontains    包含,忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
 
in:
 
    __in
     
    查询在某一范围的书
    Book.objects.filter(publish__in=[10, 20, 30])
 
is null / is not null:
 
    __isnull  判空
     
    Book.objects.filter(name__isnull=True)    // 查询用户名为空的书
    Publish.objects.filter(name__isnull=False)  // 查询用户名不为空的书
 
不等于/不包含于:
 
    Book.objects.filter().excute(publishe=10)    // 查询出版社不为10的书
    Book.objects.filter().excute(publish__in=[10, 20])  // 查询出版社不在 [10, 20] 的书

其他常用模糊查询:

    __startswith 以…开头
    __istartswith 以…开头 忽略大小写
    __endswith 以…结尾
    __iendswith 以…结尾,忽略大小写
    __range 在…范围内
    __year 日期字段的年份
    __month 日期字段的月份
    __day 日期字段的日

4.2双下划线(__)查询

a、双下划线(__)之单表条件查询

例子:

table1.objects.filter(id__lt=10,id__gt=1)#获取id小于10,且大于1的记录
table1.objects.filter(id__in=[11,22,33,44])#获取id在[11,22,33,44]中的记录
table1.objects.exclude(id__in=[11,22,33,44])#获取id不在[11,22,33,44]中的记录
table1.objects.filter(name__contains="content1")#获取name中包含有"contents"的记录(区分大小写)
table1.objects.filter(name__icontains="content1")#获取name中包含有"content1"的记录(不区分大小写)
 
table1.objects.filter(id__range=[1,4])#获取id在1到4(不包含4)之间的的记录

b、双下划线(__)之多表条件查询

正向查找(条件)之一对一查询

#查询书名为"python"的书的id号
res3=Book.objects.filter(title="python").values("id")
print(res3)

正向查找(条件)之一对多查询

#查询书名为"python"的书对应的出版社的地址
res4=Book.objects.filter(title="python").values("publisher__city")
print(res4)
 
#查询"aaa"作者所写的所有的书的名字
res5=Book.objects.filter(author__name="aaa").values("title")
print(res5)
 
#查询"aaa"作者所写的所有的书的名字(与上面的用法没区别)
res6=Book.objects.filter(author__name="aaa").values("title")
print(res6)

反向查找之一对多查询

#查询出版了书名为"python"这本书的出版社的名字
res7=Publisher.objects.filter(book__title="python").values("name")
print(res7)
 
#查询写了书名为"python"的作者的名字
res8=Publisher.objects.filter(book__title="python").values("book__authors")
print(res8)

反向查找之多对多查询

#查询所写的书名为"python"的作者的名字
res9=Author.objects.filter(bool__title="python").values("name")
print(res9)
条件查询即与对象查询对应,是指filter,values等方法中的通过__来明确查询条件

4.3F查询和Q查询

F查询专门取对象中某列值的操作,F的作用:用来批量修改数据的

#导入F
from django.db.models import F
#把table1表中的num列中的每一个值在的基础上加10
table1.objects.all().update(num=F("num")+10)

Q构建搜索条件, Q的作用:Q是用来做条件查询的

#导入Q
from django.db.models import Q
 
Q对象可以对关键字参数进行封装,从而更好的应用多个查询
#查询table2表中以"aaa"开头的所有的title列
q1=table2.objects.filter(Q(title__startswith="aaa")).all()
print(q1)

Q对象可以组合使用&,|操作符,当一个操作符是用于两个Q对象时,会产生一个新的Q对象

#查找以"aaa"开头,或者以"bbb"结尾的所有title
Q(title__startswith="aaa") | Q(title__endswith="bbb")

Q对象可以用"~"操作符放在表达式前面表示否定,也可允许否定与不否定形式的组合

#查找以"aaa"开头,且不以"bbb"结尾的所有title
Q(title__startswith="aaa") & ~Q(title__endswith="bbb")

Q对象可以与关键字参数查询一起使用,Q对象放在关键字查询参数的前面

查询条件:

#查找以"aaa"开头,以"bbb"结尾的title且书的id号大于4的记录
Q(title__startswith="aaa") | Q(title__endswith="bbb"),book_id__gt=4

九、实例

1、Django的ORM中如何判断查询结果是否为空,判断django中的orm为空

result= Booking.objects.filter()

方法一 .exists()

if result.exists():
    print "QuerySet has Data"
else:
    print "QuerySet is empty"

方法二 .count()==0

if result.count() == 0:
    print "empty"

方法三

if result:
    print "QuerySet has Data"
else:
    print "QuerySet is empty"

总结:

QuerySet.exists() > QuerySet.count()==0 > QuerySet

2、模板中显示数据库内容的方法

a、创建数据库

from django.db import models
from django.db import models
 
class Business(models.Model):
    caption = models.CharField(max_length=32)
    code = models.CharField(max_length=32)
 
class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(protocol='both',db_index=True)
    port = models.IntegerField()
    business = models.ForeignKey(to='Business',to_field='id',on_delete=models.CASCADE)

business.html




    
    Title


    

业务线列表(对象)

    {% for row in v1 %}
  • {{ row.id }}-{{ row.caption }}-{{ row.code }}
  • {% endfor %}

业务线列表(字典)

    {% for row2 in v2 %}
  • {{ row2.id }}-{{ row2.caption }}
  • {% endfor %}

host.html




    
    Title


    

主机列表(对象)

{% for row in v1 %} {% endfor %}
主机ID IP 端口 业务线名称
{{ row.hostname }} {{ row.ip }} {{ row.port }} {{ row.business.caption }}

主机列表(字典)

{% for row in v2 %} {% endfor %}
主机ID 主机名 业务线ID 业务线名称
{{ row.nid }} {{ row.hostname }} {{ row.business__id }} {{ row.business__caption }}

主机列表(元祖)

{% for row in v3 %} {% endfor %}
主机ID 主机名 业务线ID 业务线名称
{{ row.0 }} {{ row.1 }} {{ row.2 }} {{ row.3 }}

views.py

from django.shortcuts import render,HttpResponse
from app01 import models
 
def business(request):
    # 第一种方式(是个对象)
    v1 = models.Business.objects.all()
    # 第二种方式,只取id和caption(是个字典)
    v2 = models.Business.objects.all().values('id','caption')
    return render(request,'business.html',{'v1':v1,'v2':v2})
 
def host(request):
    #总共三种方式,对象,字典,列表
    v1 = models.Host.objects.all()
    v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','business__id','business__caption')
    v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','business__id','business__caption')
    return render(request,'host.html',{'v1':v1,'v2':v2,'v3':v3})
勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:IT世界里的《三十而已》:不比包包的男士们在比什么?

下一篇:windows下配置anaconda和pytorch

您可能感兴趣

  • 2020年iOS面试反思总结

    Object-C系列面试题总结 基础题: 1.Objective-C的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么不要在category中重写一个类原有的方法? 答: Objective-c的类不可以有多继承,OC里面都是单继承,多继承可以用protocol委托代理来模拟实现 可以实现多个接口,可以通过实现多个接口完成OC的多重继承...

  • Google 推荐在 MVVM 架构中使用 Kotlin Flow

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:HiDhl 链接:https://juejin.im/post/5f153adff265da22fb287e6e 声明:本文已获HiDhl授权发表,转发等请联系原作者授权 前言 在之前分享过一篇 Jetpack 综合实战应用 神奇宝贝(PokemonGo) 眼前一亮的 Jetpack + MVVM 极简实...

  • sql 获取数据库字段信息_使用DBATools获取SQL数据库详细信息

    sql 获取数据库字段信息 In the series of articles on DBATools, (see TOC at the bottom) we are exploring useful DBATools command to perform administrative SQL tasks. In this article, we will explore useful co...

  • CNN如何用于NLP任务?一文简述文本分类任务的7个模型

    点击上方,选择星标或置顶,每天给你送干货! 阅读大概需要20分钟 跟随小博主,每天进步一丢丢 选自 | Ahmed BESBES 作者 | Ahmed Besbes 转自 | 机器之心 本文介绍了用于文本分类任务的 7 个模型,包括传统的词袋模型、循环神经网络,也有常用于计算机视觉任务的卷积神经网络,以及 RNN + CNN。 本文是我之前写过的一篇基于推特数据进行情感分析的文章,那时我建立...

  • MES系统整体解决方案

    项目概述统接入服务 项目目标 以柔性制造系统、敏捷制造等信息化改造为建设目标,利用传感技术、无线通信技术、计算机网络技术、智能数字化技术、物联网应用服务平台技术等多种现代化技术,打造基于物联网的综合示范平台,建立起一个示范性应用基地。 通过WIP(在制品管理)+SCADA(设备联网)实现敏捷制造的生产管理目标,以信息可视化提供的数据支撑,准确掌握各类生产的资源负荷状况,提高瓶颈资源利用率,提...

  • 干货 | 携程度假无线前端架构演进之路

    作者简介 Jade Gu,携程高级前端开发专家,负责度假前端框架设计和 Node.js 基础设施建设等工作。 这篇文章将简略地介绍我们当前的无线前端架构设计及其演进之路。主要内容包含以下几个部分,希望我们的经验能带给大家一些启发。 1)当前的前端方案及其解决的问题 2)现在面对的新挑战 3)我们的前端方案设计和选择。 一、当前的前端方案及其解决的问题 1.1 当前方案的技术背景 将时间调回到...

  • power bi数据分析_Power BI数据模型:使用关系

    power bi数据分析 In this article, we look at how to create different types of relationships between two or more tables in the Power BI data model. 在本文中,我们研究如何在Power BI数据模型中的两个或多个表之间创建不同类型的关系。 Anyone wh...

  • DBATools PowerShell SQL Server数据库备份命令

    In my earlier PowerShell SQL Server article, SQL Database Backups using PowerShell Module – DBATools, we explored the importance of a disaster recovery solution for an organization. Microsoft offer...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。