DJango 模型层之创建多表以及增查改删

一、先创建几个关联表:

from django.db import models

# 创建一对多、一对一的时候,属性名不需要加_'id',django会自动添加
# 创建多对多的时候,创建出来的表名会以    '本类名_属性名' 为表名
#     并且创建出来的表格只会有三个字段
#         第一个是id
#         第二个是类名_id
#         第三个是(to='Author')author_id
class Book(models.Model):
    # 设置了unique=True:title字段不能重复,是唯一的
    title = models.CharField(max_length=32,unique=True)
    # 设置了null=True:price字段可以为空
    price = models.DecimalField(max_digits=8, decimal_places=2,null=True)
    pub_date = models.DateField()
    # 创建与出版社一(book)对多(publish)的字段
    publih=models.ForeignKey(to='Publish',to_field='id',on_delete=models.CASCADE,null=True)

#     跟作者多对多创建第三张表
    authors = models.ManyToManyField(to='Author')

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()


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


class AuthorDetail(models.Model):
    gf = models.CharField(max_length=32)
    tel = models.CharField(max_length=32)
    # 作者与作者信息一对一的创建关联字段
    author = models.OneToOneField(to='Author',to_field='id',on_delete=models.CASCADE)
models.py

创建以前最好先弄清楚个表之间的关系:

  一对多:在多的表内创建关联字段

  多对多:创建第三张表

  一对一:在任意表格内创建关联字段

注意事项:  

  •  id 字段是自动添加的
  •  这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。
  •  定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。
  • 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

 

一对多关系:

# 先创建publish表内容
    models.Publish.objects.create(name='新华出版社', email='qwe123@163.com', addr='北京')
    models.Publish.objects.create(name='人民出版社', email='ewe333@163.com', addr='上海')

    # 创建book表内容
    # 方式一(关联字段写被关联表的主键,推荐使用)
    book = models.Book.objects.create(title='新华字典',price=10,pub_date='1990-12-5',publih_id=1)
    print(book.title)

    # 方式二(关联字段写被关联的对象)
    publish = models.Publish.objects.filter(name='人民出版社').first()
    book = models.Book.objects.create(title='西游记',price=81,pub_date='2009-1-14',publih=publish)

    print(book.publih.name)
View Code

多对多关系:

 author = models.Author.objects.create(name='魏建功',age=50)
    print(author.name)
    models.Author.objects.create(name='施耐庵', age=80)
    models.Author.objects.create(name='吴承恩',age=100)
    models.Author.objects.create(name='某人',age=45)
    models.Author.objects.create(name='任某',age=54)
    # 创建关系要先拿到对象
    book = models.Book.objects.filter(title='新华字典').first()
    wei = models.Author.objects.filter(name='魏建功').first()
    book.authors.add(wei)

    book = models.Book.objects.filter(title='水浒传').first()
    shi = models.Author.objects.filter(name='施耐庵').first()
    book.authors.add(shi)

    book = models.Book.objects.filter(title='西游记').first()
    wu = models.Author.objects.filter(name='吴承恩').first()
    book.authors.add(wu)

    book = models.Book.objects.filter(title='电子书').first()
    mou = models.Author.objects.filter(name='某人').first()
    ren = models.Author.objects.filter(name='任某').first()
    book.authors.add(mou,ren)
    # 也可以写成:book.authors.add(*[mou,ren]) *的意思是打散的意思


    # 清除这本书绑定的作者
    book.authors.clear()

    # 重置,重新编写这本的与作者的绑定
    # book.authors.set()  注意括号内要写一个可迭代对象,例如一个列表
    book = models.Book.objects.filter(id=4).first()
    ren = models.Author.objects.filter(name='任某').first()
    mou = models.Author.objects.filter(name='某人').first()
    book.authors.set((ren,mou))

    # 解除书与作者之间的关系
    book.authors.remove(ren)
    # remove与add都是可以用*[obj,....]
View Code

理解下面代码:

  # 返回一个对象,与这本书关联的出版社对象
    # print(book.publih)
    #返回一个queryset,列表内存放了与这本书关联的作者对象
    # print(book.authors.all())

一对多查询:

一对多:book表与publish表是一对多关系
    正向查询:关联属性在book表中,所以book对象找关联的出版社对象,是正向查询
    反向查询:关联属性在book表中,所以出版社对象找关联书籍,是反向查询
    所以:
    正向查询:       按照字段查询 book(是obj).publish
    book -------------------------------------------->  publish
    反向查询:按照小写表名_set.all()查询  publish(是obj).book_set().all()
    publish ------------------------------------------>   book
 # 正向查询示例:
    # 查询水浒传这本的出版社名称
    book = models.Book.objects.filter(title='水浒传').first()
    print(book.publih.name)
    # 反向查询示例:
    # 查询新华出版社出版的书籍名称
    publish= models.Publish.objects.filter(name='新华出版社').first()
    print(publish.book_set.all().values('title'))
View Code

多对多查询:

多对多:book表与author表是一对多关系
      正向查询:关联属性在book表中,所以book对象找关联的作者集合,是正向查询
      反向查询:关联属性在book表中,所以作者对象找关联书籍,是反向查询
      所以:
      正向查询:       按照字段查询 book(是obj).authors.all()
      book -------------------------------------------->  author
      反向查询:按照小写表名_set.all()查询  author(是obj).book_set().all()
      author ------------------------------------------>   book
# 查询电子书这本书关联的作者姓名和年龄
    book = models.Book.objects.filter(title='电子书').first()
    print(book.authors.all().values('name','age'))
    # 查询任某出版过的书籍名称
    ren = models.Author.objects.filter(name='任某').first()
    print(ren.book_set.all().values('title'))
View Code

一对一查询:

 一对一:author表与authordetail表是一对多关系
          正向查询:关联属性在authordetail表中,所以authordetail对象找关联的作者,是正向查询
          反向查询:关联属性在authordetail表中,所以作者对象找作者信息,是反向查询
          所以:
          正向查询:       按照字段查询 ad(是obj).author
          authordetail -------------------------------------------->  author
          反向查询:按照 小写表名 查询  author(是obj).authordetail
          author ------------------------------------------>   authordetail
# 查钢蛋对应的人名
    ad = models.AuthorDetail.objects.filter(gf='钢蛋').first()
    print(ad.author.name)

    # 查任某对应的gf
    author = models.Author.objects.filter(name='任某').first()
    print(author.authordetail.gf)
View Code

 

基于双下划线的跨表查询

 # 正向查询按字段,反向查询按表名小写(适用于一对多,多对多,一对一)

    # 1、查询西游记这本书的出版社名字
    # 正向查询
    # ret = models.Book.objects.filter(title='西游记').values('publih__name')
    # print(ret)
    # 反向查询
    # ret = models.Publish.objects.filter(book__title='西游记').values('name')
    # print(ret)


    # 2、查询西游记这本书籍的所有作者的姓名和年龄
    # 正向查询
    # retr = models.Book.objects.filter(title='西游记').values('authors__name','authors__age')
    # print(retr)
    # 反向查询
    # ret = models.Author.objects.filter(book__title='西游记').values('name','age')
    # print(ret)


    # 查询某人的女盆友的名字
    # 正向查询
    # ret = models.Author.objects.filter(name='某人').values('ad__gf')
    # print(ret)

    # 反向查询
    # ret = models.AuthorDetail.objects.filter(author__name='某人').values('gf')
    # print(ret)

    # 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
    # ret = models.Author.objects.filter(ad__tel__startswith=151).values('book__title','book__publih__name')
    # print(ret)
    # ret = models.Book.objects.filter(authors__ad__tel__startswith=151).values('title','publih__name')
    # print(ret)
View Code

聚合与分组

#####################聚合#####################
    # 聚合函数使用,使用aggregate方法
    from django.db.models import Avg,Count,Max,Min,Sum
    # 查询全部书籍的平均价格
    # ret = models.Book.objects.all().aggregate(price = Avg('price'))
    # print(ret)
    # 查询全部书籍的做高价格
    # ret = models.Book.objects.all().aggregate(Max('price'))
    # print(ret)
    # 使用方法
    # models.单表名.objects.all().aggergate(统计函数(统计字段))


    ###################分组###########
    # 单表查询每个部门的平均工资
    # ret = models.Emp.objects.values('dep').annotate(Avg('salary'))
    # print(ret)
    # 单表分组使用方法:
    #models.单表名.objects.values('group by 字段').annotate(统计函数(统计字段))
View Code

 练习:

# 练习
    # 1、统计每一个出版社的最便宜的书
    ret = models.Publish.objects.values('name').annotate(m = Min('book__price')).values('name','book__title')
    print(ret)

    # 2、统计每一本书的作者个数
    ret = models.Book.objects.annotate(c = Count('authors__name')).values('title','c')
    print(ret)


    # 3、统计每一本以py开头的书籍的作者个数:
    ret = models.Book.objects.filter(title__startswith='py').values('title').annotate(c = Count('authors__name')).values('title','c')
    print(ret)

    # 4、统计不止一个作者的图书:
    ret = models.Book.objects.values('title').annotate(c = Count('authors__name')).filter(c__gt=1).values('title','c')
    print(ret)

    # 5、根据一本图书作者数量的多少对查询集 QuerySet进行排序
    ret = models.Book.objects.values('title').annotate(c = Count('authors__name')).values('title','c').order_by('c')
    print(ret)
View Code

F与Q查询:

 ############# F 与 Q ################
    from django.db.models import F, Q
    ############# F 查询 ################
    # ret = models.Book.objects.all().update(price=F('price')+100)


    ################### Q 查询 可以是用&、|、~ #############
    ret = models.Book.objects.filter(Q(title='西游记')|Q(price=101)&Q(pub_date__year=2001))
    print(ret)
View Code

 

posted @ 2018-06-28 19:48  xiaofeinie  阅读(101)  评论(0)    收藏  举报