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) ...