首页 > 数据库 >【Django基础】操作数据库详解

【Django基础】操作数据库详解

时间:2023-11-24 23:14:29浏览次数:34  
标签:__ name objects models 数据库 Django filter 详解 id

django ORM简介

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

Django ORM框架的功能:

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

数据库的配置

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

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

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

#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 pymysqlpymysql.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

关系字段

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('?')
  1. reverse():
 reverse()  

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

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

  my_queryset.reverse()[:5]  

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

6.distinct():

distinct(*fields)

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

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

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

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

  \# 列表中包含的是Student对象

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

  <QuerySet [<Student: Lin Student>]>  

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

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

  <QuerySet [{'id': 1, 'name': 'Linxiao', 'age': 20}]>  

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

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

  <QuerySet [{'id': 1, 'name': 'Linxiao', 'age': 20}]>

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

  <QuerySet [{'id': 1, 'name': 'Linxiao'}]>

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>业务线列表(对象)</h1>
    <ul>
        {% for row in v1 %}
            <li>{{ row.id }}-{{ row.caption }}-{{ row.code }}</li>
        {% endfor %}
    </ul>
    <h1>业务线列表(字典)</h1>
    <ul>
        {% for row2 in v2 %}
            <li>{{ row2.id }}-{{ row2.caption }}</li>
        {% endfor %}
    </ul>
 
</body>
</html>

host.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>主机列表(对象)</h1>
    <table border="1">
        <tread>
            <tr>
                <th>主机ID</th>
                <th>IP</th>
                <th>端口</th>
                <th>业务线名称</th>
            </tr>
        </tread>
        <tbody>
            {% for row in v1 %}
                <tr>
                    <td>{{ row.hostname }}</td>
                    <td>{{ row.ip }}</td>
                    <td>{{ row.port }}</td>
                    <td>{{ row.business.caption }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
 
    <h1>主机列表(字典)</h1>
    <table border="1">
        <tread>
            <tr>
                <th>主机ID</th>
                <th>主机名</th>
                <th>业务线ID</th>
                <th>业务线名称</th>
            </tr>
        </tread>
        <tbody>
            {% for row in v2 %}
                <tr>
                    <td>{{ row.nid }}</td>
                    <td>{{ row.hostname }}</td>
                    <td>{{ row.business__id }}</td>
                    <td>{{ row.business__caption }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
 
    <h1>主机列表(元祖)</h1>
    <table border="1">
        <tread>
            <tr>
                <th>主机ID</th>
                <th>主机名</th>
                <th>业务线ID</th>
                <th>业务线名称</th>
            </tr>
        </tread>
        <tbody>
            {% for row in v3 %}
                <tr>
                    <td>{{ row.0 }}</td>
                    <td>{{ row.1 }}</td>
                    <td>{{ row.2 }}</td>
                    <td>{{ row.3 }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>

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})

标签:__,name,objects,models,数据库,Django,filter,详解,id
From: https://www.cnblogs.com/fuchangjiang/p/17854975.html

相关文章

  • 【Django基础】Mysql数据库连接配置
    Django支持MySQL5.7及以上版本。Django的inspectdb功能使用information_schema数据库,其中包含所有数据库架构的详细数据。Django希望数据库支持Unicode(UTF-8编码),并将执行事务和引用完整性的任务交给它。django连接MySQL数据库,需要安装第三方数据库mysqlclientpip......
  • 【Django基础】Django新建项目
    安装Djangopipinstalldjango直接在pycharm中新建Django项目会自动安装django模块新建第一个项目django-adminstartprojectmysite项目目录mysite/manage.pymysite/__init__.pysettings.pyurls.pyasgi.pywsgi.p......
  • django13days
    csrf跨站请求伪造钓鱼网站:模仿一个正规的网站让用户在该网站上做操作但是操作的结果会影响到用户正常的网站账户但是其中有一些猫腻 eg:英语四六级考试需要网上先缴费但是你会发现卡里的钱扣了但是却交到了一个莫名其妙的账户并不是真正的四六级官方账户模拟钓鱼......
  • Jaeger Client Go 链路追踪|入门详解
    目录从何说起Jaeger部署Jaeger从示例了解JaegerClientGo了解trace、spantracer配置Sampler配置Reporter配置分布式系统与span怎么调、怎么传HTTP,跨进程追踪客户端Web服务端Tag、Log和Ref 从何说起之前参加柠檬大佬的训练营(免费白嫖),在大......
  • Java泛型Generics​入门详解
    Java泛型Generics泛型基础知识泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。泛型的格式:<数据类型>注意:泛型只能支持引用数据类型。如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型,此时可以往集合中添加任意的数据类型。带来一个坏处是由于......
  • 【Django基础】auth认证模块
    https://www.cnblogs.com/DuoDuosg/p/17005583.html一、django的auth认证模块1.什么是auth模块Auth模块是Django自带的用户认证模块:我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,......
  • Profinet转ModbusTCP网关详解
    Profinet转ModbusTCP网关详解Profinet转ModbusTCP网关是一种常见的工业通信设备,广泛应用于现代工业自动化系统中。通过将Profinet协议转换成ModbusTCP协议,实现了不同网络之间的互联互通。这种网关设备具有简单、可靠的特点,能够满足不同设备之间的数据传递需求。在实际应用中,Prof......
  • SqlServer 数据库表死锁
    数据库表死锁 spid  锁表进程tableName  被锁表名declare@spid intSet@spid =618--锁表进程declare@sqlvarchar(1000)set@sql='kill'+cast(@spid asvarchar)exec(@sql)select  request_session_id  spid,OBJECT_NAME(resource_associated_entity_i......
  • 详解CCE服务:一站式告警配置和云原生日志视图
    本文分享自华为云社区《新一代云原生可观测平台之CCE服务日志和告警篇》,作者:云容器大未来。告警和日志是运维人员快速定位问题、恢复异常的主要手段。运维人员日常的工作模式往往是先接收告警信息,再根据告警信息初步判断异常的范围和影响,通过相关组件的日志定位出故障原因,进行系......
  • (转)Git详解
    原文:https://juejin.cn/post/7067165972901134373#heading-0一、什么是版本控制1、什么是版本控制版本控制(Revisioncontrol)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。实现跨区域多......