ORM多表操作

表关系介绍

表与表关系

表与表关系有3种方式
一对一(利用 OneToOneField 产生关联关系)
多对一(利用 ForeignKey 产生关联关系)
多对多(利用 ManyToManyField 产生关联关系)
关联后产生的表是什么样子?
一对1会产生属性_id

默认指向主键 可能是隐藏主键 djamgo1.1默认级联(models. SET NULL解除级联)

一对一

先建立少的一方

from django.db import models

# Create your models here.
class Us(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=10)
    bday = models.DateField()
    checked = models.BooleanField()

class Uss(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=10)
    bday = models.DateField()
    gl = models.OneToOneField(to="Us",to_field="id",on_delete=models.CASCADE)
to对应被关联的表 to_field对应被关联的id(不填默认主键) on_delete=models.CASCADE 设置级联更新

被关联表

1571238885693

关联表

1571238941167

多对1


被关联表

1571239190883

关联表

1571239239496

多对多

from django.db import models

# Create your models here.
class Us(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=10)
    bday = models.DateField()
    checked = models.BooleanField()


class Udud(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=10)
    bday = models.DateField()
    dszb=models.ManyToManyField('Us')

us表

1571283393468

udud表

1571283413712

第3张表dszb

1571283447850

多表增删改查表数据

创建表代码

from django.db import models

class Author(models.Model):
    """
    作者表
    """
    name = models.CharField(max_length=32, verbose_name='作者名')
    age = models.IntegerField(verbose_name='年龄')
    au = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)

    # class Meta:  # 不可以用
    #     db_table = 'app01_author'  # 指定表名 不用这个 也没事
    #     ordering = ['-id']  # 用于排序
    #     verbose_name = '作者表'  # 显示作用

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    """
    作者详细信息表
    """
    birthday = models.DateField(verbose_name='生日')
    telephone = models.CharField(max_length=11, verbose_name='手机号')
    addr = models.CharField(max_length=64, verbose_name='地址')

    # class Meta:  #
    #     ordering = ['id']  # 用于排序
    #     verbose_name = '作者详细信息表'  # 显示作用

    def __str__(self):
        return self.telephone + self.addr


class Publish(models.Model):
    """
    出版社表
    """
    name = models.CharField(max_length=32, verbose_name='出版社名字')
    city = models.CharField(max_length=32, verbose_name='出版社城市')

    def __str__(self):
        return self.name

    # class Meta:  #
    #     ordering = ['id']  # 用于排序
    #     verbose_name = '出版社表'  # 显示作用


class Book(models.Model):
    """
    书籍表
    """
    title = models.CharField(max_length=32, verbose_name='书籍名字')
    publishDate = models.DateField(verbose_name='书籍出版日期')
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='书价格')
    publishs = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField('Author')

    def __str__(self):
        return self.title

    # class Meta:  #
    #     ordering = ['id']  # 用于排序
    #     verbose_name = '出版社表'  # 显示作用

from django.db import models

# Create your models here.

class Author(models.Model):
    """
    作者表
    """
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    # authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)
    au=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class AuthorDetail(models.Model):
    """
    作者详细信息表
    """
    birthday=models.DateField()
    telephone=models.CharField(max_length=11)
    addr=models.CharField(max_length=64)
    # class Meta:
        # db_table='authordetail' #指定表名
        # ordering = ['-id',]
    def __str__(self):
        return self.telephone + self.addr


class Publish(models.Model):
    """
    出版社表
    """
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)
    def __str__(self):
        return self.name

class Book(models.Model):
    """
    书籍表
    """
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
    authors=models.ManyToManyField('Author',)

    def __str__(self):
        return self.title



多表增加

多表增加 有2种方式 一种是直接利用字段增加 一种是利用找到的mode对象增加
下面是 代码示例
一对一 和 一对多 方法相同

一对一 和 一对多

第一种方式 利用新生成的字段增加
models.Author.objects.create(
    name='海狗',
    age=59,
    au_id=4
)

第2种方式(与id为4的就是一对一关系)ghj
au_obj = models.AuthorDetail.objects.get(id=4)
第一种方式
models.Author.objects.create(
    name='海狗',
    age=59,
    au=au_obj
)

一对多
pub_obj = models.Publish.objects.get(id=3)
models.Book.objects.create(
    title='xx2',
    price=13,
    publishDate='2011-11-12',
    # publishs=pub_obj , #类属性作为关键字时,值为model对象
    publishs_id=3  # 如果关键字为数据库字段名称,那么值为关联数据的值
)

多对多

第一种
new_obj = models.Book.objects.create(
    title='海狗产后护理第二部',
    price=0.5,
    publishDate='2019-09-29',
    publishs_id=2,
)

new_obj.authors.add(3, 5)  # #*args  **kwargs
new_obj.authors.add(*[3, 5])  # 用的最多,


第2种
ziwen = models.Author.objects.get(id=3)
haigou = models.Author.objects.get(id=5)

new_obj = models.Book.objects.create(
    title='海狗产后护理第二部',
    price=0.5,
    publishDate='2019-09-29',
    publishs_id=2,
)

new_obj.authors.add(ziwen, haigou)

删除

一对一 一对多 删除都是找到mode对象delete()就行
多对多就比较特殊 要先找到对象 在点属性 进行修改
一对一
# models.AuthorDetail.objects.filter(id=3).delete()
一对多
models.Publish.objects.filter(id=3).delete()

# 多对多
book_obj = models.Book.objects.get(id=2)
book_obj.authors.clear()  # 清除
book_obj.authors.set(['1','5'])  # 先清除再添加,相当于修改

找到对象直接改
第一种
models.Book.objects.filter(id=5).update(
    title='华丽丽',
    publishs=ret,
    publishs_id=1,
)
第2种
ret = models.Publish.objects.get(id=2)
models.Book.objects.filter(id=5).update(
    title='华丽丽',
    publishs=ret,
)

跨表查询子查询

查询2种方式 (正向查询,反向查询)  关系属性写在表1,关联到表2,那么通过表1的数据去找表2的数据,叫做正向查询,返过来就是反向查询

正向查询用 属性
反向查询用 表名(小写的)
注意 
    多对多 反向查询用 表名_set
    只要含义多个的可能性都用all全部查询出来 在for循环 得到信息
下面是查询实列

查询实列

# 查询
# 一对一
# 关系属性写在表1,关联到表2,那么通过表1的数据去找表2的数据,叫做正向查询,返过来就是反向查询
# 查询一下王洋的电话号码

# 正向查询  对象.属性
# obj = models.Author.objects.filter(name='王洋').first()
# ph = obj.au.telephone
# print(ph)

# 查一下电话号码为120的作者姓名
# 反向查询  对象.小写的表名
# obj = models.AuthorDetail.objects.filter(telephone=120).first()
# ret = obj.author.name  #陈硕
# print(ret)

# 一对多
# 查询一下 海狗的怂逼人生这本书是哪个出版社出版的  正向查询
# obj = models.Book.objects.filter(title='海狗的怂逼人生').first()
# ret = obj.publishs.name
# print(ret)  #24期出版社
#  查询一下 24期出版社出版过哪些书
# obj = models.Publish.objects.filter(name='24期出版社').first()
#
# ret = obj.book_set.all() #<QuerySet [<Book: 母猪的产后护理>, <Book: 海狗的怂逼人生>]>
# for i in ret:
#     print(i.title)

# 多对多
# 海狗的怂逼人生 是哪些作者写的 -- 正向查询
# obj = models.Book.objects.filter(title='海狗的怂逼人生').first()
# ret = obj.authors.all()
#
# print(ret)  #<QuerySet [<Author: 王洋>, <Author: 海狗>]>
# for i in ret:
#     print(i.name)

# 查询一下海狗写了哪些书 -- 反向查询
# obj = models.Author.objects.filter(name='海狗').first()
# ret = obj.book_set.all()
# print(ret)
# for i in ret:
#     print(i.publishs.name)
#     print(i.title)
# return HttpResponse('ok')

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

正向查询用属性 反向用表名

# 一对一
# 查询一下王洋的电话号码
正向查询
# ret = models.Author.objects.filter(name='王洋').values('au__telephone')
反向查询
# ret = models.AuthorDetail.objects.filter(author__name='王洋').values('telephone')
# print(ret) #<QuerySet [{'au__telephone': '110'}]> #<QuerySet [{'telephone': '110'}]>
#

# 一对多
# 海狗的怂逼人生这本书是哪个出版社出版的
正向查询
# ret = models.Book.objects.filter(title='海狗的怂逼人生').values('publishs__name')
# print(ret) #<QuerySet [{'publishs__name': '24期出版社'}]>
反向查询
# ret = models.Publish.objects.filter(book__title='海狗的怂逼人生').values('name')
# print(ret) #<QuerySet [{'name': '24期出版社'}]>



多对多
    # 海狗的怂逼人生 是哪些作者写的 -- 正向查询
    # obj = models.Book.objects.filter(title='海狗的怂逼人生').first()
    # ret = obj.authors.all()
    #
    # print(ret)  #<QuerySet [<Author: 王洋>, <Author: 海狗>]>
    # for i in ret:
    #     print(i.name)

    # 查询一下海狗写了哪些书 -- 反向查询
    # obj = models.Author.objects.filter(name='海狗').first()
    # ret = obj.book_set.all()
    # print(ret)
    # for i in ret:
    #     print(i.publishs.name)
    #     print(i.title)

分组查询

    # 每个出版社出版的书的平均价格
    # 用的是publish表的id字段进行分组
    # ret = models.Book.objects.values('publishs__id').annotate(a=Avg('price'))
    # 用的book表的publishs_id字段进行分组
    # ret = models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
    # print(ret)
    # ret = models.Publish.objects.annotate(a=Avg('book__price')).values('a')
    # print(ret) #<QuerySet [{'a': None}, {'a': 71.166667}, {'a': 6.0}]>

聚合查询(求和等)

ret = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price'))
print(ret) 
#{'price__avg': 45.1, 'price__max': Decimal('200.00')} python字典格式,也就是说,聚合查询是orm语句的结束

F查询(同表 字段比较 更新)

from django.db.models import Avg, Sum, Max, Min, Count,F
查询一下评论数大于点赞数的书
# ret = models.Book.objects.filter(comment__gt=F('good'))
# print(ret)


将所有书的价格上调100块
# models.Book.objects.all().update(
#     price=F('price')+100
# )

Q查询(与或非)

    from django.db.models import Avg, Sum, Max, Min, Count, F,Q
    ret = models.Book.objects.filter(Q(id=2)&Q(Q(price__gt=112)|~Q(comment__lte=200)))
    print(ret)

admin添加用户

python manage.py createsuperuser
输入用户名:wuchao
邮箱不用输 直接回车
输入密码:必须超过8位,并且别太简单

admin注册

from django.contrib import admin

# Register your models here.

from app01 import models

admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
admin.site.register(models.Publish)
admin.site.register(models.Book)

admin添加用户

python manage.py createsuperuser
输入用户名:wuchao
邮箱不用输 直接回车
输入密码:必须超过8位,并且别太简单
posted @ 2020-03-02 17:44  一起奥利给  阅读(308)  评论(0编辑  收藏  举报