VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • django之模型层

配置测试脚本

第一种方法:

  • 直接在某一个应用下的test文件中书写(前四行代码去manage.py中拷贝):

    import os
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
    
        import django
        django.setup()
    

第二种方法:

直接新建一个任意名称的py文件 在里面写上上面的配置

ORM单表操作

先前操作

# 模型类
class Books(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_date = models.DateField()

创建数据

# 方式1:create方法
models.Books.objects.create(title='三国演义', price=345.66, publish_date='2019-11-27')

# 方式2:利用对象的绑定方法
book_obj = models.Books(title='红楼梦', price=235.66, publish_date='2018-09-12')
book_obj.save()

修改数据

# 方式1:利用queryset方法
res = book_obj = models.Books.objects.filter(pk=1).update(price=320.23)
print(res)    # <QuerySet [<Books: Books object>]>


# 方式2:利用对象 (不推荐使用)   利用对象修改 内部其实是从头到尾将数据的所有字段都重新写一遍
book_obj = models.Books.objects.get(pk=2)
book_obj.price = 150.33
book_obj.save()

注:

  • pk会自动查找当前表的主键字段
  • filter查询出来的结果是一个QuerySet对象

QuerySet对象特点

  • 只要是QuerySet对象就可以无限制的调用QuerySet的方法

    book_obj = models.Books.objects.filter(pk=1).filter().filter()
    # 可以无限制 的删选
    
  • 只要是QuerySet对象就可以用句点符 点query查看当前内部对应的sql语句

    book_obj = models.Books.objects.filter(pk=1)
    print(book_obj.query)
    

get和filter区别

  • filter获取到的是一个queryset对象,类似于一个列表
  • get获取到的直接就是数据对象本身
  • 当条件不存在时,filter不报错直接返回一个空,get直接报错

删除数据

# 方式1:
models.Books.objects.filter(pk=7).delete()

# 方式2:
book_obj = models.Books.objects.get(pk=6)
book_obj.delete()

必知必会13条操作

如果想要在终端查看 orm对应的sql语句,可以在settings.py中加配置

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

1. all() 查询所有

返回的是queryset对象

res = models.Books.objects.all()
print(res)

注意:orm语句的查询默认是惰性查询,只有当你真正使用数据的时候才会执行orm语句

2. filter() 筛选

相当于原生SQL语句的where

res = models.Books.objects.filter(pk=3, title='人')  # 可以传多个参数,and关系
print(res)

3. get()

筛选,获取的是数据对象本身,条件不存在时报错, 而且查询条件只能是一个

res = models.Books.object.get(pk=2)
print(res)

4. first()

取queryset中第一个数据对象

res = models.Books.objects.filter(title='西游记').first()
print(res.price)

5. last()

取queryset中最后一个数据对象

res = models.Books.objects.filter(title='西游记').last()
print(res)

6. count()

统计数据的个数

num = models.Books.objects.count()
print(num)

7. values()

获取对象中指定字段的值,可以传多个参数,返回的是 queryset对象 列表套字典

res = models.Books.objects.values('title','price')
print(res)

8. values_list()

获取对象中指定字段的值,可以传多个参数,返回的是 queryset对象 列表套元组

res = models.Books.objects.values_list('title','price')
print(res)

9. order_by()

按照指定的字段排序, 默认是升序

降序只要在字段前面加负号(-)

res = models.Books.objects.order_by('price')
res = models.Books.objects.all().order_by('price')   # 两者等价,默认是升序

res = models.Books.objects.order_by('-rice')

10. reverse()

颠倒顺序的前提是 颠倒的对象必须要有顺序(提前排序之后才能颠倒顺序)

所以必须和order_by联用

res = models.Books.objects.order_by('price')
res1 = models.Books.objects.all().order_by('price').reverse()
print(res1)

11. exclude()

排除

res = models.Books.objects.all().exclude(title='人间失格')
print(res)

12. exists()

判断查询结果是否有值,返回结果是一个布尔值

res = models.Books.objects.filter(pk=12).exists()
print(res)

13. distinct()

对查询结果去重,但是必须要有完全相同的数据,才能去重

注意:主键id不一样,会忽略

res = models.Books.objects.values('title','price').distinct()
print(res)

双下划线查询

  • __gt 大于
  • __lt 小于
  • __gte 大于等于
  • __lte 小于等于
  • __range 范围查询 顾头顾尾
  • __in 在里面
  • __year
  • __month
# 查询价格大于200的书籍
res = models.Books.objects.filter(price__gt=200)
print(res)

# 查询价格小于300 的书籍
res = models.Books.objects.filter(price__lt=200)
print(res)

# 查询价格大于等于200
res = models.Books.objects.filter(price__gte=200)
print(res)

# 查询价格小于等于200
res = models.Books.objects.filter(price__lte=200)
print(res)

# 查询价格在200~300之间的书籍
res = models.Books.objects.filter(price__range(200, 300))   # 顾头顾尾
print(res)

# 查询价格是200 或 300 的书籍
res = models.Books.objects.filter(price__in[200, 300])
print(res)

# 查询出版日期为2019年的书籍
res = models.Books.objects.filter(publish_date__year=2019)
print(res)


# 查询出版日期是11月份的书籍
res = models.Books.objects.filter(publish_date__month=11)
print(res)
  • __startswitch 以....开头
  • __endswith 以...结尾
  • __contains 包含 如果查询字母,默认区分大小写
  • __icontains 加 i 忽略大小写
# 查询书籍是以“人”开头的书
res = models.Books.objects.filter(title__startswith='人')
print(res)

# 查询书籍是以“梦”结尾的书
res = models.Books.objects.filter(title__endswith='梦')
print(res)

# 查询书籍名称中包含“的”字的书籍
res = models.Books.objects.filter(title__contains='的')
print(res)

# 查询书籍名称中包含字母p的书籍
res = models.Books.objects.filter(title__contains='p')   # 默认区分大小写
res = models.Books.objects.filter(title__icontains='p')  # 加i不区分大小

一对多字段外键增删改查

准备工作

先建立图书表、出版社表、作者表、作者详情表

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    publish = models.ForeignKey(to='Publish')
    authors = models.ManyToManyField(to='Author')


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)


class Author(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()

    author_detail = models.OneToOneField(to='AuthorDetail')


class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=64)

花式操作

增:

# 方法1 :直接传表里面的实际字段
models.Book.objects.create(title='人间失格', price=123.56, publish_id=1)

# 方法2 :传虚拟字段  跟数据对象即可
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='水浒传', price=223.45, publish=publish_obj)

改:

# 方法1: 直接传实际字段
models.Book.objects.filter(pk=1).update(publish_id=2)

# 方法2:传数据对象
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

删:

# 默认就是级联删除 级联更新
models.Publish.objects.filter(pk=1).delete()

多对多外键字段的增删改查

增:add

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(1)   # book_obj.authors 就已经进入第三张表了

book_obj.authors.add(1, 2)  # 添加两个书籍作者



# 同样支持传数据对象
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj)

# 数据对象也支持传多个
book_obj = models.Book.objects.filter(pk=2).first()
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj1, author_obj2)

add方法 能够想第三张关系表添加数据

  • 支持传数字
  • 也支持传对象,并且两者都可以是多个

改:set

# 方法1:传字段
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set([1, 3])
book_obj.authors.set([1,])   # set里面要传可迭代对象

# 方法2:传数据对象
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj1,author_obj2))

set方法 能修改多对多关系表中的数据

  • 可以传数字,也可以传对象,都支持传多个
  • set里面传的是可迭代对象

删:remove

# 方法1:传字段
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(1)
book_obj.authors.remove(1, 2)   # 支持多个


# 方法2:传数据对象
book_obj = models.Book.objects.filter(pk=1).first()
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.authors.remove(author_obj)

remove方法 能删除多对多关系表中的数据

  • 可以传数字,也可以传对象,
  • 都支持传多个, 不需要传迭代对象

清空:clear

book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear()

clear清空数据,括号里面不需要传参数

跨表查询

正反向查询

  • 正向查询 关系字段在谁那,由有关系字段的表查,就是正向查询
  • 反向查询 关系字段不在那

正向查询按字段,反向查询按表名小写 + _set

基于对象的跨表查询(子查询)

# 1.查询书籍主键为2的出版社名称
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish.name)

# 2.查询书籍主键为4的作者姓名
book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.authors)    # app01.Author.None
print(book_obj.authors.all())  # 当正向查询点击外键字段数据有多个的情况下 需要.all()

# 3.查询作者是式微的手机号码
author_obj = models.Author.objects.filter(name='式微').first()
print(author_obj.author_detail.phone)


# 4.查询出版社是东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all())

# 5.查询手机号是120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author.name)

# 6.查询作者是无名写过的书籍
author_obj = models.Author.objects.filter(name='无名').first()
print(author_obj.book_set.all())

总结:

  • 正向查询,点击外键字段数据有多个的情况下 需要.all()
  • 反向查询,一对多和多对多需要表名 + _set,一对一不需要加_set

基于双下划线的跨表查询(联表查询)

# 1.查询书籍pk为2的出版社名称
res = models.Book.objects.filter(pk=2).values('publish__name')
print(res)
res = models.Publish.objects.filter(book__pk=2).values('name')

# 2.查询书籍pk为2的作者姓名和邮箱
res = models.Book.objects.filter(pk=2).values('authors__name', 'authors__email')
print(res)
res = models.Author.objects.filter(book__pk=2).values('name', 'email')

# 3.查询作者是邶风的家庭地址
res = models.Author.objects.filter(name='邶风').values('author_detail__addr')
print(res)
res = models.AuthorDetail.objects.filter(author__name='邶风').values('addr')


# 4.查询出版社是东方出版社出版过的书的名字
res = models.Publish.objects.filter(name='东方出版社').values('book__title')
print(res)
res = models.Book.objects.filter(publish__name='东方出版社').values('title')


# 5. 查询书籍pk是2的作者的手机号
res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
print(res)
res = models.Author.objects.filter(book__pk=2).values('author_detail__phone')

相关教程