django orm

models.py:

from django.db import models

# Create your models here.

class Publisher(models.Model):
    name = models.CharField(max_length=255, verbose_name='出版社')
    address = models.CharField(max_length=255, verbose_name='地址')

    class Meta:
        verbose_name = '出版社'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class Athor(models.Model):
    name = models.CharField(max_length=50, unique=True, verbose_name='作者')
    age = models.SmallIntegerField(verbose_name='年龄')
    choices = ((1, ''), (2, ''))
    sex = models.SmallIntegerField(choices=choices, default=1)

    class Meta:
        verbose_name = '作者'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=64, unique=True, verbose_name='书名')
    athor = models.ManyToManyField(Athor, verbose_name='作者')
    publisher = models.ForeignKey(Publisher, verbose_name='发行出版社')

    class Meta:
        verbose_name = '书籍'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

 

查询所有书籍:

>>> books = models.Book.objects.all()
>>> for book in books:
...     print(book.name)
... 
三国演义
西游记
水浒传
红楼梦
陆小凤传奇
三少爷的剑
>>>

查询‘三国演义’这本书:

>>> books = models.Book.objects.get(name='三国演义')
>>> books.name
'三国演义'

#要注意的是,get方法如果要查询的书不存在的话,会抛出错误
>>> book2 = models.Book.objects.get(name='四国演义')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/huangxm/.pyenv/versions/django196/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/huangxm/.pyenv/versions/django196/lib/python3.5/site-packages/django/db/models/query.py", line 385, in get
    self.model._meta.object_name
book.models.DoesNotExist: Book matching query does not exist.

#这种情况可以用filter来查询
>>> book2 = models.Book.objects.filter(name='四国演义')
>>> book2
<QuerySet []>
>>> for book in book2:
...     print(book.name)
... 
>>> 
#结果为空,表示没有查询到
查找第一条和最后一条数据:
>>> book = models.Book.objects.last()
>>> book.name
'三少爷的剑'
>>> book = models.Book.objects.first()
>>> book.name
'三国演义'
>>>

filter:

#多条件查找
>>> book = models.Publisher.objects.filter(name='人民邮电出版社', address='人民路')

#模糊查询,__连接
>>> book = models.Publisher.objects.filter(address__contains='')
>>> for i in book:
...     print(i.name, i.address)
... 
电子工业出版社 工业路
人民邮电出版社 人民路
机械工业出版社 机械路

#模糊查询,忽略大小写
>>> book = models.PUblisher.objects.filter(address__icontains='Zeng')

#查询年龄在列表中的人
>>> athor = models.Athor.objects.filter(age__range=[99,99999])
>>> for i in athor:
...     print(i.name)
... 
吴承恩
施耐庵
罗贯中
曹雪芹
高鹗
薜兴国
古龙

#startswith, endswith, istartswith, iendswith
>>> publisher = models.Publisher.objects.filter(address__startswith='')
>>> for i in publisher:
...     print(i.name)
... 
人民邮电出版社

 

添加数据:

#添加出版社
new_publisher = models.Publisher(name='阳光出版社', address='阳光路")
new_publisher.save()

#使用create添加,这种方式不需要save()
models.Publisher.objects.create(name='阳光出版社', address=‘阳光路’)

 

批量修改数据:

#修改id为1,2,3的作者性别,update方法不需要save(),而且效率比较高
>>> models.Athor.objects.filter(id__range=[1,3]).update(sex=2)
3
>>> athor_obj = models.Athor.objects.filter(id__range=[1,3])
>>> for i in athor_obj:
...     print(i.id, i.name, i.sex)
... 
1 网络写手one 2
2 言情写手 2
3 玄幻写手 2

 

连锁查询:

#查询所有作者,并按年龄排序,如果想倒着排序order_by('-age')
>>> p = models.Athor.objects.all().order_by('age')
>>> for i in p:
...     print(i.name, i.age)
... 
薜兴国 99
古龙 99
吴承恩 99999
施耐庵 99999
罗贯中 99999
曹雪芹 99999
高鹗 99999

#对查询结果计数
>>> models.Publisher.objects.filter(address__endswith='').count()
3

 

外键(一对多)查询:

从具有ForeignKey的表查询称为正向查询,反过查称为反向查询

正向查询:

>>> obj = models.Book.objects.filter(publisher__name='电子工业出版社')
>>> for i in obj:
...     print(i.name)
... 
三国演义
陆小凤传奇
三少爷的剑


#查询书的出版社
>>> obj = models.Book.objects.filter(name='西游记')
>>> for i in obj:
...     print(i.publisher)
... 
人民邮电出版社

反向查询,从出版社查书

#查询id为3的出版社出版的书
>>> obj = models.Publisher.objects.get(id=3)
>>> books = obj.book_set.all()
>>> for book in books:
...     print(book.name, book.publisher)
... 
水浒传 机械工业出版社
红楼梦 机械工业出版社

 

一对多添加数据:

#通过外键字段的ID进行添加
>>> models.Book.objects.create(name='长篇小说', publisher_id=1)
<Book: 长篇小说>

#字典形式
>>> dic = {'name': '短篇小说', 'publisher_id':2}
>>> models.Book.objects.create(**dic)
<Book: 短篇小说>


#通过对象添加
>>> publisher_obj = models.Publisher.objects.filter(name='阳光出版社')
>>> models.Book.objects.create(name='小小说', publisher=publisher_obj[0])
<Book: 小小说>

多对多查询:

一本书可以有多个作者,一个作者可以写很多书

#查询书的所有作者
>>> b1 = models.Book.objects.get(name='陆小凤传奇')
>>> a = b1.athor.select_related()
>>> for i in a:
...     print(i, i.name, i.age)
... 
薜兴国  薜兴国  99
古龙  古龙   99

 

多对多添加数据:

正向添加数据:当我们要添加一本书籍的时候,先正常添加作者和书籍,然后我们找到这些书籍和作者,再为书籍添加作者

#添加一本新书
>>> models.Book.objects.create(name='新书籍', publisher_id=1)
<Book: 新书籍>
#找到这本书
>>> book_obj = models.Book.objects.get(name='新书籍')
#找出作者们
>>> athor_obj = models.Athor.objects.filter(id__range=[1,3])
#为书籍添加这些作者
>>> book_obj = models.Book.objects.get(name='新书籍')
>>> book_obj.athor.add(*athor_obj)

反向添加数据:获取书籍,获取作者,为作者添加书籍

>>> book_obj = models.Book.objects.get(name='新书籍')
>>> athor_obj = models.Athor.object.filter(id_range[1,3])
>>> athor_obj.book_set.add(*book_obj)

 

自定义多对多中间表:

在多对多关系中,Django会自动创建多对多的中间表,中间表中两个外键字段,分别关联到多对多的两张表中;但大多数情况下,我们需要手动创建中间表,因为我们可能需要在中间表中添加其它字段;

那我们如何来自定义中间表呢?修改一下models.py 中的book, 再定义AthorRelation表:

class Book(models.Model):
    name = models.CharField(max_length=64, unique=True, verbose_name='书名')
    #如果要使用自定义第三张表那么需要throught来定义第三张表名
    athor = models.ManyToManyField(Athor, verbose_name='作者', through='AthorRelation')
    publisher = models.ForeignKey(Publisher, verbose_name='发行出版社')

    class Meta:
        verbose_name = '书籍'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

#自定义多对多的第三张表
class AthorRelation(models.Model):
    athor = models.ForeignKey(Athor)
    book = models.ForeignKey(Book)

    class Meta:
        verbose_name = '书籍作者对应关系表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.book.name

查询有两种方法:

第一种:

#正向查,从manytomany字段所在表查起
>>> book_obj = models.Book.objects.get(name='青云志')
>>> for i in book_obj.athor.all():
...     print(i)
... 
玄幻写手
言情写手
#反向查
>>> athor_obj = models.Athor.objects.get(name='玄幻写手')
>>> athor_obj.book_set.all()
<QuerySet [<Book: 青云志>]>
>>> for i in athor_obj.book_set.all():
...     print(i)
... 
青云志

第二种方法:比较简单,直接从中间表下手:

>>> rel = models.AthorRelation.objects.all()
>>> for i in rel:
...     print(i.athor.name, i.book.name)
... 
玄幻写手 青云志
言情写手 青云志

#使用filter
>>> rel = models.AthorRelation.objects.filter(book__name='青云志')
>>> for i in rel:
...     print(i.book.name, i.athor.name)
... 
青云志 玄幻写手
青云志 言情写手

添加数据:

当我们使用了自定义的中间表时,多对多添加数据的add方法就不能使用了,我们可以直接操作第三张表来添加数据,更加简单直接:

1. 通过对象添加, 笨方法

>>> models.AthorRelation.objects.create(
              athor=models.Athor.objects.get(id=3),
              book=models.Book.objects.get(id=2)
)

2. 通过ID来添加,比较简洁

>>> models.AthorRelation.objects.create(athor_id=2, book_id=2)
<AthorRelation: 长篇小说>

 

删除数据:

先查询一下:

>>> obj = models.AthorRelation.objects.all()
>>> for i in obj:
...     print(i.book.name, i.athor.name)
... 
长篇小说 玄幻写手
长篇小说 言情写手
小小说 玄幻写手
小小说 灵异写手

删除一个作者:

>>> obj=models.AthorRelation.objects.all()
>>> obj
<QuerySet [<AthorRelation: 长篇小说>, <AthorRelation: 小小说>]>
>>> for i in obj:
...     print(i.book.name, i.athor.name)
... 
长篇小说 言情写手
小小说 灵异写手

删除书籍长篇小说:

>>> book_obj = models.Book.objects.get(name='长篇小说')
>>> book_obj.delete()
(2, {'book.Book': 1, 'book.AthorRelation': 1})
>>> rel = models.AthorRelation.objects.all()
>>> for i in rel:
...     print(i.book.name, i.athor.name)
...
可以看出:当我们删除一条记录时,中间表中对应的记录也会被删除。
posted @ 2016-08-19 14:52  黄小墨  阅读(505)  评论(0编辑  收藏  举报