Django - 模型层 - 下

一、多表 sql 

单表

多表
多对一 多对多 一对一

===============================================

一对多:
Book
id title price publish_id
1 php 100 1
2 python 200 1
3 go 300 2
Publish
id name email addr
1 人名出版社 @ 北京
2 沙河出版社 @ 沙河

一旦确定是 一对多
怎么建立一对多的关系?---》 关联字段 ,建在‘多’的表中

查询python这本书的出版社的邮箱
(子查询)
select email from Publish where id = (
select publish_id from Book where title = 'python'
)

===============================================

多对多:(彼此一对多)
Book
id title price publish_id
1 php 100 1
2 python 200 1
3 go 300 2
Author
id name age addr
1 alex 34 beijing
2 egon 29 nanjing
Book2Author
id book_id author_id
1 2 1
2 2 2
3 3 2

alex 出版过的书籍名称 (子查询:以一个查询的结果作为下一个查询的条件)
select title from Book where id in (
select book_id from Book2Author where author_id = (
select id from Author where name = 'alex'
)
)

===============================================

一对一:
Author
id name age authordetail_id(unique) (一定要加)
1 alex 34 1
2 egon 29 2
AuthorDetail (这个信息不经常查,为了效率,扩展)
id addr gender tel gf_name
1 beijing male 110 小花
2 nanjing male 911 红花

===============================================

总结:
一旦确定是 一对多
怎么建立一对多的关系?---》 关联字段 ,建在‘多’的表中
一旦确定是 多对多
怎么建立多对多的关系?---》 创建第三张表(关联表): id 和 两个关联字段
一旦确定是 一对一
怎么建立一对一的关系?---》 在两张表中的任意一张表中建立关联字段 + unique

Publish
Book
AuthorDetail
Author
Book2Author
=====================================================
create table publish(
id int primary key auto_increment,
name varchar(20)
);
create table book(
id int primary key auto_increment,
title varchar(20),
price decimal(8,2),
pub_date date,
publish_id int,
foreign key (publish_id) references publish(id)
);
create table authordetail(
id int primary key auto_increment,
tel varchar(20)
);
create table author(
id int primary key auto_increment,
name varchar(20),
age int,
authordetail_id int unique,
foreign key (authordetail_id) references authordetail(id)
);
create table book2author(
id int primary key auto_increment,
book_id int,
author_id int
);

=====================================================

二、创建模型

'''
Book
Publish
Author
AuthorDetail
Book2Author  会自定生成

Book    --   Publish        一对多
Author  --   AuthorDetail   一对一
Book    --   Author         多对多  Book2Author

'''
from django.db import models

# 作者详情表
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    birthday = models.DateField()
    telephone = models.BigIntegerField()
    addr = models.CharField(max_length=64)

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    # 一对一 关系 这里会生成一个字段 authordetail_id
    authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    # def __str__(self):  # 打印的时候 可以打印出name
    #     return self.name

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)

    # 一对多 关系  # 这里会生成一个 字段 publish_id
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    '''
        publish_id int,
        foreign key (publish_id) references publish(id)
    '''

    # 多对多  # 这里会生成第三张表 book_authors
    authors = models.ManyToManyField(to='Author')
    '''
        create table book_authors(
            id int primary key auto_increment,
            book_id int,
            author_id int
        );
    '''

    def __str__(self):
        return self.title

# 这里生成第三张表的本质 # django 去写不用我们写
# class Book2Author(models.Model):
#     nid = models.AutoField(primary_key=True)
#     book = models.ForeignKey(to='Book')  # 默认关联主键
#     author = models.ForeignKey(to='Author')

'''
数据库迁移
    python manage.py makemigrations
    python manage.py migrate
'''

'''  
注:
# 这就是django2.0问题  
    authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid')
    TypeError: __init__() missing 1 required positional argument: 'on_delete'
解决办法:
     authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)
     publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
     
     需要加上 on_delete = models.CASCADE
     
     django1 默认加上了 on_delete 

'''

 

生成表如下:

 

 

 

 

 

注意事项:

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

三、多表 - 添加

from django.shortcuts import render,HttpResponse

from app01.models import *

def add(request):

    # 单表
    pub = Publish.objects.create(name='人名出版社',city='陕西',email='1234@qq.com')

    # =============================绑定一对多的关系==================================
    # 方式一  book -- publish
    book_obj = Book.objects.create(title='西游记',publishDate='2012-12-1',price=100,publish_id=1)
    print(book_obj.title)       #  西游记
    print(book_obj.publish)     # Publish object (1)
    print(book_obj.publish_id)  # 1

    # 方式二
    pub_obj = Publish.objects.filter(nid = 2).first()  # 对象
    book_obj = Book.objects.create(title='放风筝得人',publishDate='2012-1-2',price=150,publish=pub_obj)
    print(book_obj.title)      # 放风筝得人
    print(book_obj.price)      # 150
    print(book_obj.publish_id) # 3
    print(book_obj.publish)    # Publish object (3)
    print(book_obj.publish.name)    # 人名出版社
    print(book_obj.publish.city)    # 陕西

    # 查询西游记这本书,出版社对应的邮箱
    book_obj = Book.objects.filter(title='西游记').first()
    print(book_obj.publish.email)  # yuan@163.com

# =============================绑定多对多的关系================================== book_obj = Book.objects.create(title='西游记',publishDate='2009-11-20',price=100,publish_id=3) egon = Author.objects.get(name='egon') alex = Author.objects.get(name='alex') # Book_author django 自己加的 你没办法操作 加数据 # django 找到第三张表 添加数据 绑定多对多关系的API book_obj.authors.add(egon,alex) book_obj.authors.add(1,2) book_obj.authors.add(*[1,2]) # # 等效于 传位置参数时 加 * # 解除 多对多的 关系 book_obj = Book.objects.filter(nid=4).first() book_obj.authors.remove(2) book_obj.authors.remove(1,2) book_obj.authors.remove(*[1,2]) # 全解除 book_obj.authors.clear() # 查询出所有作者对象集合 print(book_obj.authors.all()) # #queryset [obj1.obj2] # 与这本书关联的所有作者对象 # 查询主键为4 的书籍的 所有作者的名字 print(book_obj.authors.all().values('name')) # # <QuerySet [{'name': 'alex'}, {'name': 'egon'}]>

http://www.cnblogs.com/yuanchenqi/articles/8963244.html

http://www.cnblogs.com/yuanchenqi/articles/8978167.html

add(obj1[, obj2, ...])

create(**kwargs)

remove(obj1[, obj2, ...])

clear()

set()方法

 

 

四、查询 - 基于对象 - 跨表

def add(request):

    # =============================基于对象的跨表查询===================
    '''   
        一对多
            按字段 :publish (正向查询按字段)
            book  ----》 publish
                 《---   
                 按表名 book_set.all() (反向查询按表名)
    '''
    '''   
        一对一
            按字段 :authordetail (正向查询按字段)
            author  ----》 authordetail
                   《---   
                  按表名 author   (反向查询按表名)
    '''
    '''   
        多对多
            按字段 :authors (正向查询按字段)
            book  ----》 author
                 《---   
               按表名 book_set.all()  (反向查询按表名)
    '''
    '''
    (0.000) select city from publish where nid =(
       select publish_id from book where nid = 1;
     ) 
     ---------------基于对象的sql 子查询-----------------
     SELECT 
         "app01_book"."nid", 
         "app01_book"."title", 
         "app01_book"."publishDate", 
         "app01_book"."price",
         "app01_book"."publish_id" 
     FROM "app01_book"
       WHERE 
         "app01_book"."nid" = 1 
       ORDER BY 
         "app01_book"."nid" ASC LIMIT 1; args=(1,)

    SELECT 
       "app01_publish"."nid",
       "app01_publish"."name", 
       "app01_publish"."city",
       "app01_publish"."email" 
     FROM "app01_publish" 
     WHERE 
     "app01_publish"."nid" = 1; args=(1,)

     '''

    # 正向查询 按字段
    #  查询主键为1的书籍的出版社所在的城市
    book_obj = Book.objects.filter(nid = 1).first()
    print(book_obj.publish.city)  # beijing


    # 反向查询 按表名
    # 查询人名出版社出版的所有书籍的名称
    publish_obj = Publish.objects.filter(name='人名出版社').first()
    print(publish_obj.book_set.all())  # queryset [book1,book2]
    # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>,...]>
    # for obj in publish_obj.book_set.all():
    #     print(obj.title)


    # 正向查询
    # 查询alex的手机号
    alex = Author.objects.filter(name='alex').first()
    print(alex.authordetail.telephone)


    # 反向查询
    # 查询手机号为119 的作者名字
    ad = AuthorDetail.objects.filter(telephone=119).first()
    print(ad.author.name)


    # 正向查询
    # 查询三国演义所有作者的名字
    book_obj = Book.objects.filter(title='三国演义').first()
    print(book_obj.authors.all().values('name'))
    # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    # <QuerySet [{'name': 'alex'}, {'name': 'egon'}]>


    # 反向查询
    # alex 出版过的所有书籍的名称
    alex = Author.objects.filter(name='alex').filter()
    print(alex.book_set.all())
    print(alex.book_set.all().values('title'))
    # <QuerySet [<Book: 金瓶书>, <Book: 三国演义>]>
    # <QuerySet [{'title': '金瓶书'}, {'title': '三国演义'}]>

    # for obj in alex.book_set.all():
    #     print(obj.title)
    # 金瓶书
    # 三国演义

注意:

你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改:

  publish = ForeignKey(Book, related_name='bookList')

那么接下来就会如我们看到这般:

  # 查询 人民出版社出版过的所有书籍

  publish=Publish.objects.get(name="人民出版社")
  book_list=publish.bookList.all()  # 与人民出版社关联的所有书籍对象集合

五、查询 - 基于双下划线(join)- 跨表

Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。

关键点:正向查询按字段,反向查询按表名。

def add(request):

    # =============================基于双下划线 (queryset)(sql 是join 查询) 的跨表查询===================
    # 不分一对一,一对多  正向查询按字段 反向查询 按表名
    # 1. 查询人名出版社出版过的所有书籍的名称和价格(一对多)
    ret = Publish.objects.filter(name='人名出版社').values('book__title','book__price')
    print(ret)
    '''
     <QuerySet [{'book__title': '红楼梦1','book__price': Decimal('100.00')}, 
     {'book__title': '红楼梦2', 'book__price': Decimal('100.00')}, 
     {'book__title': '红楼梦3', 'book__price': Decimal('100.00')}, 
     {'book__title': '红楼梦4', 'book__price': Decimal('100.00')}, 
     {'book__title': '红楼梦5', 'book__price': Decimal('100.00')}, 
     {'book__title': '西游记', 'book__price': Decimal('100.00')}]>

     SELECT 
         "app01_book"."title", 
         "app01_book"."price" 
     FROM 
         "app01_publish" 
     LEFT OUTER JOIN "app01_book" ON 
         ("app01_publish"."nid" = "app01_book"."publish_id") 
     WHERE 
         "app01_publish"."name" = '人名出版社1' LIMIT 21; args=('人名出版社1',)


     '''

    ret = Book.objects.filter(publish__name='人名出版社').values('title','price')
    print(ret)
    '''
      <QuerySet [{'title': '三国演义', 'price': Decimal('200.00')}, 
      {'title': '三国演义2', 'price': Decimal('200.00')}, 
      {'title': '金瓶mei', 'price': Decimal('200.00')}]>

      SELECT 
          "app01_book"."title", 
          "app01_book"."price" 
      FROM 
          "app01_book" 
      INNER JOIN "app01_publish" ON 
          ("app01_book"."publish_id" = "app01_publish"."nid")
      WHERE 
          "app01_publish"."name" = '人名出版社2' LIMIT 21; args=('人名出版社2',)


      '''

    # 2.查询alex 出版过的所有书籍的名字(多对多) join 的sql 语句 正向按字段 反向按表名
    ret = Author.objects.filter(name='alex').values('book__title')
    # <QuerySet [{'book__title': '金瓶mei'}, {'book__title': '三国演义'}]>

    ret = Book.objects.filter(authors__name='alex').values('title')
    # <QuerySet [{'title': '金瓶mei'}, {'title': '三国演义'}]>

    # 3.混合使用
    # 查询人名出版社出版过的所有书籍的名字以及作者的名字
    ret = Book.objects.filter(publish__name='人名出版社').values('title','authors__name')
    # <QuerySet [{'title': '三国演义', 'authors__name': 'alex'},{'title': '金瓶shu', 'authors__name': None}]>
    '''
         (0.000)SELECT 
             "app01_book"."title", 
             "app01_author"."name" 
         FROM 
             "app01_book" 
         INNER JOIN "app01_publish" ON 
             ("app01_book"."publish_id" = "app01_publish"."nid") 
         LEFT OUTER JOIN "app01_book_authors" ON 
             ("app01_book"."nid" = "app01_book_authors"."book_id") 
         LEFT OUTER JOIN "app01_author" ON 
             ("app01_book_authors"."author_id" = "app01_author"."nid") 
         WHERE 
             "app01_publish"."name" = '人名出版社2' LIMIT 21; args=('人名出版社2',)

     '''
    # 混合使用 手机号以151 开头的作者出版过的所有书籍名称以及出版社名称
    ret = Book.objects.filter(authors__authordetail__telephone__startswith = '151').values('title','publish__name')
    print(ret)
    # <QuerySet [{'title': '金瓶mei', 'publish__name': '人名出版社2'}, {'title': '三国演义', 'publish__name': '人名出版社2'}]>
    '''
        (0.000) SELECT 
            "app01_book"."title", 
            "app01_publish"."name" 
        FROM "app01_book" 
        INNER JOIN "app01_book_authors" ON 
            ("app01_book"."nid" = "app01_book_authors"."book_id") 
        INNER JOIN "app01_author" ON 
            ("app01_book_authors"."author_id" = "app01_author"."nid") 
        INNER JOIN "app01_authordetail" ON 
            ("app01_author"."authordetail_id" = "app01_authordetail"."nid") 
        INNER JOIN "app01_publish" ON 
            ("app01_book"."publish_id" = "app01_publish"."nid") 
        WHERE 
            "app01_authordetail"."telephone" LIKE '151%' ESCAPE '\' LIMIT 21; args=('151%',)

    '''

 

注意:

反向查询时,如果定义了related_name ,则用related_name替换表名,例如:

  publish = ForeignKey(Blog, related_name='bookList')

六、聚合查询 - 分组查询

def add(request):

    # =============================聚合查询与分组查询==============================
    # 1.计算所有图书的平均价格
    # select avg(price) from book  (avg count sum min )
    from django.db.models import Avg,Max,Count

    ret = Book.objects.all().aggregate(c = Avg('price'))
    # {'price__avg': 160.0}  {'c': 160.0}

    ret = Book.objects.all().aggregate(Max('price'))
    # {'price__max': Decimal('200.00')}

    # 分组 统计每一本书 作者的个数   (group by)
    ret = Book.objects.all().annotate(c = Count('authors__name'))
    print(ret)  # 查询出的结果 看不出 需要 循环 查看count
    for obj in ret:
        print(obj.title,obj.c)
    '''
       红楼梦 0
       三国演义 2
       三国 0
    '''
    '''
     (0.000) SELECT 
         "app01_book"."nid", 
         "app01_book"."title", 
         "app01_book"."publishDate", 
         "app01_book"."price", 
         "app01_book"."publish_id", 
     COUNT("app01_author"."name") AS "c" 
     FROM "app01_book" 
     LEFT OUTER JOIN "app01_book_authors" ON 
         ("app01_book"."nid" = "app01_book_authors"."book_id") 
     LEFT OUTER JOIN "app01_author" ON 
         ("app01_book_authors"."author_id" = "app01_author"."nid") 
     GROUP BY 
         "app01_book"."nid", "app01_book"."title", "app01_book"."publishDate", "app01_book"."price", "app01_book"."publish_id"; args=()

     '''

    # 统计每一个作者出版过的书籍最高价格
    ret = Author.objects.all().annotate(max_price = Max('book__price'))
    print(ret) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    for obj in ret:
        print(obj.name,obj.max_price)
        # alex  300.00
        # egon 200.00

    # 每一个出版社 出版过的书籍的平均价格
    ret = Publish.objects.all().annotate(avg_price = Avg('book__price')).values('name','avg_price')
    print(ret)
    '''
     <QuerySet [{'name': '人名出版社1', 'avg_price': 100.0}, 
      {'name': '人名出版社2', 'avg_price': 216.66666666666666},
      {'name': '人名出版社3', 'avg_price': 200.0}, 
      {'name': '人名出版社4', 'avg_price': None}, 
      {'name': '人名出版社5', 'avg_price': None}, 
      {'name': '人名出版社6', 'avg_price': None}]>

     '''
    for obj in ret:
        print(obj.name,obj.avg_price)
    '''
    人名出版社1 100.0
    人名出版社2 216.66666666666666
    人名出版社3 200.0
    人名出版社4 None
    '''

聚合

aggregate(*args, **kwargs)

    # 计算所有图书的平均价格

    >>> from django.db.models import Avg
    >>> Book.objects.all().aggregate(Avg('price'))
    {'price__avg'34.35}

aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

  >>> Book.objects.aggregate(average_price=Avg('price'))

  {'average_price'34.35}
 

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

  >>> from django.db.models import Avg, MaxMin

  >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
  {'price__avg'34.35'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

分组

annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

统计每一本书的作者个数

  bookList=Book.objects.annotate(authorsNum=Count('authors'))

  for book_obj in bookList:
    print(book_obj.title,book_obj.authorsNum)

统计每一个出版社的最便宜的书

  publishList=Publish.objects.annotate(MinPrice=Min("book__price"))

  for publish_obj in publishList:
    print(publish_obj.name,publish_obj.MinPrice)
annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:
queryResult= Publish.objects
            .annotate(MinPrice=Min("book__price"))
            .values_list("name","MinPrice")
print(queryResult)

统计每一本以py开头的书籍的作者个数:
queryResult=Book.objects
           .filter(title__startswith="Py")
           .annotate(num_authors=Count('authors'))
统计不止一个作者的图书:
queryResult=Book.objects
          .annotate(num_authors=Count('authors'))
          .filter(num_authors__gt=1)
根据一本图书作者数量的多少对查询集 QuerySet进行排序:
Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
查询各个作者出的书的总价格:
# 按author表的所有字段 group by
    queryResult=Author.objects
              .annotate(SumPrice=Sum("book__price"))
              .values_list("name","SumPrice") print(queryResult) # 按authors__name group by queryResult2=Book.objects.values("authors__name")
              .annotate(SumPrice=Sum("price"))
              .values_list("authors__name","SumPrice") print(queryResult2)

七、F查询 - Q查询

。。。 

http://www.cnblogs.com/yuanchenqi/articles/8963244.html

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例1:

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F("price")+30)

引申:

如果要修改char字段咋办?

如:把所有书名后面加上(第一版)

>>> from django.db.models.functions import Concat
>>> from django.db.models import Value
>>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

示例1:

查询作者名是小仙女或小魔女的

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

示例:查询作者名字是小仙女并且不是2018年出版的书的书名。

>>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [('番茄物语',)]>

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

例如:查询出版年份是2017或2018,书名中带物语的所有书。

>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
<QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>, <Book: 橘子物语>]>

 

八、关联管理器

。。。 http://www.cnblogs.com/yuanchenqi/articles/8978167.html 

 ===================================================================

 http://www.cnblogs.com/liwenzhou/p/8660826.html
http://www.cnblogs.com /yuanchenqi/articles/8978167.html
https://docs.djangoproject.com/en/1.11/ref/models/querysets/

九、补充知识

1. 内容回顾
    1. 常用字段和字段参数
        1. 常用字段
            1. AutoField
                primary_key=True  # 设置为主键
            2. CharField
                max_length=32     # 设置最大长度
            3. IntegerField
            4. BigInterField
            5. TextField
            6. DateField
                auto_now_add      # 创建这条数据时自动添加当前时间
                auto_now          # 每次更新的时候都自动更新时间

            7. DateTimeField
                同上
            ...

            常用参数:
                default=""        # 设置默认值
                null=True         # 可以为空
                unique=True       # 该字段在数据库中不能重复

        2. 关系字段
            1. 外键  ForeignKey
                1. 外键通常放在多(一对多的多)的那一边

                2. 参数
                    1. to=“表名”
                    2. related_name="xx"  用来替换反向查询时的 表名_set
                    3. on_delete=models.CASCADE

            2. 一对一  OneToOneField
                1. 什么时候用  作者和作者详情

            3. 多对多  ManyToManyField
                1. 三种方式
                    1.  不用ManyToMany
                    2.  自带的ManyToMany, 自动帮我创建第三张表
                    3.  自定义第三张表


                        # 相亲网站
                        # 男孩
                        class Boy(models.Model):
                            name = models.CharField(max_length=32)
                            girls = models.ManyToManyField(to='Girl', through="Info", through_fields=("boy1", "girl1"))  # 能满足多对多的关系,但是少点东西


                        # 女孩
                        class Girl(models.Model):
                            name = models.CharField(max_length=32)
                            # through_fields=('field1', 'field2'),
                            # 你把多对多建在那个表,field1就是这个表的名字
                            # field2是你目标表的表名
                            # boys = models.ManyToManyField(to=Boy, through="Info", through_fields=("girl1", "boy1"))  # 能满足多对多的关系,但是少点东西


                        # 约会记录
                        # 男孩1      女孩1
                        # 男孩2      女孩1
                        # 男孩1      女孩2


                        # 自己创建第三张表, 记录约会的记录
                        class Info(models.Model):
                            girl1 = models.ForeignKey(to=Girl)
                            boy1 = models.ForeignKey(to=Boy)

                            # 其他补充字段
                            date = models.DateTimeField(auto_now_add=True)


        3. 元信息
            # 定义元信息
            class Meta:
                ordering = ("price", )  # 默认按照价格排序
                db_table = "book"  # 指定在数据库中创建表的表名
                unique_together = ("title", "price")  # 多字段联合唯一

    2. ORM操作
        1. 单表13个    --> 永远不要怀疑自己!要自信!!!  混乱即阶梯!

            返回QuerySet的有:
                1. all()
                3. filter()
                4. exclude()

                7. values_list()  --> 元祖
                8. values()       --> 字典
                9. order_by()
                10. reverse()
                13. distinct()
            返回对象:
                2. get()
                5. first()
                6. last()
            返回数字:
                11. count()
            返回布尔值:
                12. exist()

            双下划线:
                id__lt=10
                ...

            跨表的双下划线:
                models.Book.objects.filter(author__name=“小仙女")
                models.Book.objects.filter(author__detail__age=18)
                ...

        2. 关系表的操作
            1. 外键
                1. 正向查找         --> 具体的对象
                    直接找
                2. 反向查找         --> 对象的列表
                    .表名(小写)_set.all()
            2. 多对多
                1. 正向查找
                    直接找          --> 对象的列表

                2. 反向查找
                    表名_set.all()  --> 对象的列表

                多对多才有的:
                    .create()    --> author_obj.books.create(title="番茄物语")
                    .add(1,2,3)
                    .clear()     -->清空
                    .remove(1)
                    .set([1,2,3]/QuerySet对象)
        3.聚合和分组
            1. aggregate()
            2. annotate()     ---> GROUP BY
        4. F和Q
            1. 同一张表的不同列作比较
            2. 多个条件做查询

        5. 事务
                try:
                    from django.db import transaction
                    with transaction.atomic():
                        new_publisher = models.Publisher.objects.create(name="新华出版社CCC")
                        # 再去创建新书
                        # new_book = models.Book.objects.create(title="新华字典", price=3.5, publisher_id=new_publisher.id)
                        new_book = models.Book.objects.create(titl="新华字典CCC", price=3.5, publisher=new_publisher)
                except Exception as e:
                    print(str(e))

        6. 如何在Python脚本加载Django环境
            import os
            os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目名.settings")
            import django
            django.setup()

            # 引用Django内部的变量
补充知识

事务

import os

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

    import datetime
    from app01 import models

    try:
        from django.db import transaction
        with transaction.atomic():
            new_publisher = models.Publisher.objects.create(name="火星出版社")
            models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社id
    except Exception as e:
        print(str(e))

 

Django终端打印SQL语句

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

 

在Python脚本中调用Django环境

import os

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

    from app01 import models

    books = models.Book.objects.all()
    print(books)

orm参数

https://www.cnblogs.com/liwenzhou/p/8688919.html 

posted @ 2018-05-23 18:09  Alice的小屋  阅读(295)  评论(0编辑  收藏  举报