前面几篇随笔的数据库增删改查操作都是在单表的操作上的,然而现实中不可能都是单表操作,更多的是多表操作,一对一,一对多,多对多的表结构才是我们经常需要处理的,本篇将带我们了解多表操作的一些相关操作。也会带着大家做一个简单的图书管理的小练习。

本篇导航:

一、建表

本篇继续以图书管理的例子。

模型:书籍有书名、作者、出版日期、价格,出版社,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

1、准备工作

1)创建一个项目

2)提前在mysql数据库里建立一个库

3)修改相关setting配置。(详情可以参考前面63、64、65三篇随笔)

2、建表

你如果在建表时没有添加主键,django会自动给我们的表添加一个主键id,是不是很棒0.0

1)语法

  1. 一对一:
  2. models.OneToOneField() ===>models.ForeignKey(,unique="True")
  3. 一对多:
  4. models.ForeignKey()
  5. 多对多:
  6. models.ManyToManyField()
  7.  
  8. 属性:
  9. related_name=""
  10. 可选属性用来给此次关联起名,如果不用此属性django会自动给一个名字后面查询的例子会说明(是关联的名字不是字段名)

2)建表实例

  1. #图书表
  2. class Book(models.Model) :
  3. title = models.CharField(max_length=32)
  4. publishDate = models.DateField()
  5. prince = models.DecimalField(max_digits=5,decimal_places=2)
  6.  
  7. publish = models.ForeignKey("Publish") #一对多
  8.  
  9. authorlish = models.ManyToManyField("Author") #多对多
  10.  
  11. def __str__(self) :
  12. return self.title
  13.  
  14. #出版社
  15. class Publish(models.Model) :
  16. name = models.CharField(max_length=32)
  17. addr = models.CharField(max_length=32)
  18.  
  19. def __str__(self) :
  20. return self.name
  21.  
  22. #作者表
  23. class Author(models.Model) :
  24. name = models.CharField(max_length=32)
  25. sex = models.CharField(max_length=32)
  26. age = models.IntegerField()
  27. tel = models.CharField(max_length=32)
  28. addr = models.CharField(max_length=32)
  29.  
  30. def __str__(self) :
  31. return self.name

图书、出版社、作者

这个图书的小练习中的表没有一对一关联用法用其他两个关联基本相同

3、注意

1)主键id 字段是自动添加的

2)对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名

3)外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

4)在表与表的连接中有related_name属性可以起名用于反向查询,当然不写有默认(表名_set),一对一关联可以直接用表名


二、template模版的设计

此次的小练习template是用Bootstrap框架搭建的,因为我们本篇主讲的django模版层所以会贴出代码逮捕做分析,对前端有问题的可以看以前相关随笔哦。

相关随笔推荐:

Bootstrap使用:http://www.cnblogs.com/liluning/p/7643879.html

静态文件在模版中的使用:http://www.cnblogs.com/liluning/p/7724699.html

Bootstrap官网:http://v3.bootcss.com/

模版使用:http://v3.bootcss.com/examples/dashboard/


三、添加表记录

1、一对多添加语法

  1. 方式1:
  2. publish_obj=Publish.objects.get(nid=1)
  3. Book.objects.create(title="金瓶眉",publishDate="2012-12-12",publish=publish_obj)
  4.  
  5. 方式2:
  6. Book.objects.create(title="金瓶眉",publishDate="2012-12-12",publish_id=1)

推荐使用第一种方式 第二种方式在你知道外键publish_id确切的值时可以使用

2、多对多添加语法

  1. book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",prince=69,publish_id=1)
  2.  
  3. author_yuan=Author.objects.create(name="yuan",age=23...)
  4. author_egon=Author.objects.create(name="egon",age=32...)
  5.  
  6. book_obj.authorlish.add(author_egon,author_yuan) # 将某个特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[])
  7.  
  8. book_obj.authorlish.create() #创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。

当然我们绑定的关联也可以解除:

  1. book_obj.authorlish.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])
  2. book_obj.authorlish.clear() #清空被关联对象集合。

3、一对多添加和多对多添加实例

  1. def addbook(request) :
  2. # 添加图书页面点击提交
  3. if request.method == "POST" :
  4. # 提取添加数据
  5. title = request.POST.get("title")
  6. author = request.POST.getlist("author")
  7. publishDate = request.POST.get("publishDate")
  8. prince = request.POST.get("prince")
  9. publish = request.POST.get("publish")
  10. # 出版社object
  11. publish_obj = models.Publish.objects.filter(name=publish)[0]
  12. # 添加数据到数据库
  13. book_obj = models.Book.objects.create(title=title, publishDate=publishDate, prince=prince ,publish=publish_obj)
  14. # 多对多添加
  15. for i in author :
  16. obj = models.Author.objects.filter(name=i)[0]
  17. book_obj.authorlish.add(obj)
  18. return redirect("/index/")
  19.  
  20. # 作者与出版社querySet
  21. authorList = models.Author.objects.all()
  22. publishList = models.Publish.objects.all()
  23. return render(request,"addbook.html",{"authorList":authorList,"publishList":publishList})

一对一因为没用用到不做演示 用法与其他两个关联相同

4、相关方法演示(例子选自官网)

1)add

把指定的模型对象添加到关联对象集中。

  1. b = Blog.objects.get(id=1)
  2. e = Entry.objects.get(id=234)
  3. b.entry_set.add(e)

2)create

创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象。

  1. b = Blog.objects.get(id=1)
  2. e = b.entry_set.create(
  3. headline='Hello',
  4. body_text='Hi',
  5. pub_date=datetime.date(2005, 1, 1)
  6. )

3)remove

从关联对象集中移除执行的模型对象

  1. b = Blog.objects.get(id=1)
  2. e = Entry.objects.get(id=234)
  3. b.entry_set.remove(e)

4)clear

从关联对象集中移除一切对象。

  1. b = Blog.objects.get(id=1)
  2. b.entry_set.clear()

四、查询表记录

查询相关API前面的随笔已经写到 单表查询还有双下划线查询0.0

1、双下划线单表查询

  1. models.book.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
  2.  
  3. models.book.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
  4. models.book.objects.exclude(id__in=[11, 22, 33]) # not in
  5.  
  6. models.book.objects.filter(name__contains="ven") #模糊匹配
  7. models.book.objects.filter(name__icontains="ven") # icontains大小写不敏感
  8.  
  9. models.book.objects.filter(id__range=[1, 2]) # 范围bettwen and
  10.  
  11. startswithistartswith, endswith, iendswith 

2、基于对象的跨表查询

1)一对多查询

正向查询

  1. # 查询id=1的书籍的出版社所在的城市
  2. book_obj=Book.objects.get(id=1)
  3. print(book_obj.publish.city)
  4. # book_obj.publish 是id=1的书籍对象关联的出版社对象

反向查询

  1. # 查询 人民出版社出版过的所有书籍
  2.  
  3. publish=Publish.objects.get(name="人民出版社")
  4. book_list=publish.book_set.all() # 与人民出版社关联的所有书籍对象集合
  5. for book_obj in book_list:
  6. print(book_obj.title)

2)多对多查询

正向查询

  1. # 金瓶眉所有作者的名字
  2.  
  3. book_obj=Book.objects.filter(title="金瓶眉").first()
  4. authors=book_obj.authorlish.all()
  5.  
  6. for author_obj in authors:
  7. print(author_obj.name)

反向查询

  1. # 查询egon出过的所有书籍的名字
  2. author_obj=Author.objects.get(name="egon")
  3. book_list=author_obj.book_set.all() #与egon作者相关的所有书籍
  4.  
  5. for book_obj in book_list:
  6. print(book_obj.title)

3、查询实例

1)views

  1. def index(request) :
  2. # 查看主页(图书)
  3. bookList = models.Book.objects.all()
  4. return render(request,"index.html",{"bookList":bookList})

2)template——index.html

  1. <div class="table-responsive table-bordered">
  2. <table class="table table-striped" id="student">
  3. {% block content %}
  4. <thead>
  5. <div class="row">
  6. {% block th %}
  7. <tr>
  8. <th>编号</th>
  9. <th>书名</th>
  10. <th>作者</th>
  11. <th>出版日期</th>
  12. <th>价格</th>
  13. <th>出版社</th>
  14. <th>操作</th>
  15. </tr>
  16. {% endblock th %}
  17. </div>
  18. </thead>
  19. <tbody>
  20. {% block td %}
  21. {% for book_obj in bookList %}
  22. <tr>
  23. <td>{{ forloop.counter}}</td>
  24. <td>{{ book_obj.title }}</td>
  25. <td>
  26. {% for author in book_obj.authorlish.all %}
  27. {{ author.name }}
  28. {% endfor %}
  29. </td>
  30. <td>{{ book_obj.publishDate|date:"Y-m-d" }}</td>
  31. <td>{{ book_obj.prince }}</td>
  32. <td>{{ book_obj.publish.name }}</td>
  33. <td>
  34. <a href="/editbook/{{ book_obj.id }}"><button class="btn btn-info">编辑</button></a>
  35. <a href="/delbook/{{ book_obj.id }}"><button class="btn btn-danger">删除</button></a>
  36. </td>
  37. </tr>
  38. {% endfor %}
  39. {% endblock td %}
  40. </tbody>
  41. {% endblock content %}
  42. </table>
  43. </div>

4、基于双下划线的跨表查询

Django 还提供了一种直观而高效的方式在查询中表示关联关系那就是强大的双划线

  1. # 练习1: 查询人民出版社出版过的所有书籍的名字与价格(一对多)
  2. # 正向查询 按字段:publish
  3. queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","price")
  4.  
  5. # 反向查询 按表名:book
  6. queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__price")
  7.  
  8. # 练习2: 查询egon出过的所有书籍的名字(多对多)
  9. # 正向查询 按字段:authors:
  10. queryResult=Book.objects.filter(authors__name="yuan").values_list("title")
  11.  
  12. # 反向查询 按表名:book
  13. queryResult=Author.objects.filter(name="egon").values_list("book__title","book__price")
  14.  
  15. # 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名
  16. # 正向查询
  17. queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")
  18. # 反向查询
  19. queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")
  20.  
  21. # 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
  22. queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="").values_list("title","publish__name")

练习四需要在本建表实例上添加一个authorDetail作者详细信息表将电话号等详细信息放进去与作者表建立一对一关联

5、聚合查询与分组查询

1)聚合:aggregate()

  1. # 计算所有图书的平均价格
  2. from django.db.models import Avg
  3. Book.objects.all().aggregate(Avg('price'))
  4. #{'price__avg': 34.35}

需要使用什么函数都要通过import导入 例如常用函数:Avg,Sum,Count,Max,Min

字典的key默认(字段名__函数名)也可以自己起名字average_price

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

一次也查询多个可以

  1. Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))

2)分组:annotate() 

  1. #统计每一本书的作者个数
  2. bookList=Book.objects.annotate(authorsNum=Count('authors'))
  3. for book_obj in bookList:
  4. print(book_obj.title,book_obj.authorsNum)

annotate的返回值是querySet

3)练习

  1. # 统计每一个出版社的最便宜的书
  2. queryResult=Book.objects.values("publish__name").annotate(MinPrice=Min('price'))
  3.  
  4. # 统计每一本以py开头的书籍的作者个数
  5. queryResult=Book.objects .filter(title__startswith="Py").annotate(num_authors=Count('authors'))
  6.  
  7. # 统计不止一个作者的图书
  8. queryResult=Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)
  9.  
  10. # 根据一本图书作者数量的多少对查询集 QuerySet进行排序
  11. Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
  12.  
  13. # 查询各个作者出的书的总价格
  14. # 按author表的所有字段 group by
  15. queryResult=Author.objects.annotate(SumPrice=Sum("book__price")).values_list("name","SumPrice")
  16.  
  17. #按authors__name group by
  18. queryResult2=Book.objects.values("authors__name").annotate(SumPrice=Sum("price")).values_list("authors__name","SumPrice")

五、修改表记录

修改和以前的一样还是update比较简单就不做详细解释了直接上实例

  1. def editbook(request,id) :
  2. # 点击保存POST提交
  3. if request.method == "POST" :
  4. # 提取数据
  5. id = request.POST.get("id")
  6. title = request.POST.get("title")
  7. author_name = request.POST.getlist("author")
  8. publishDate = request.POST.get("publishDate")
  9. prince = request.POST.get("prince")
  10. publish_name = request.POST.get("publish")
  11. # 出版社object
  12. publish_obj = models.Publish.objects.get(name=publish_name)
  13. # 移除旧关联
  14. book_obj = models.Book.objects.filter(id=id)[0]
  15. book_obj.authorlish.clear()
  16.  
  17. # 更新图书表
  18. models.Book.objects.filter(id=id).update(title=title, publishDate=publishDate, prince=prince,publish_id=publish_obj)
  19.  
  20. book_obj = models.Book.objects.filter(id=id)[0]
  21. # 添加新关联
  22. for i in author_name :
  23. print(i)
  24. obj = models.Author.objects.filter(name=i)[0]
  25. book_obj.authorlish.add(obj)
  26. return redirect("/index/")

虽然修改比较简单就一句update搞定,可是因为现在图书表和作者表是多对多连接所以在更新图书表时需要清楚之前的连键和建立新的连接,语法在之前都有讲解在代码中也都标记出来了。


六、删除表记录

实例:

  1. def delbook(request,id) :
  2. # 删除图书
  3. models.Book.objects.filter(id=id).delete()
  4. return redirect("/index/")

在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。


七、图书管理小练习(只贴上图书的增删改查代码)

1、model 建表

  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. #图书表
  6. class Book(models.Model) :
  7. title = models.CharField(max_length=32)
  8. publishDate = models.DateField()
  9. prince = models.DecimalField(max_digits=5,decimal_places=2)
  10.  
  11. publish = models.ForeignKey("Publish") #一对多
  12.  
  13. authorlish = models.ManyToManyField("Author") #多对多
  14.  
  15. def __str__(self) :
  16. return self.title
  17.  
  18. #出版社
  19. class Publish(models.Model) :
  20. name = models.CharField(max_length=32)
  21. addr = models.CharField(max_length=32)
  22.  
  23. def __str__(self) :
  24. return self.name
  25.  
  26. #作者表
  27. class Author(models.Model) :
  28. name = models.CharField(max_length=32)
  29. sex = models.CharField(max_length=32)
  30. age = models.IntegerField()
  31. tel = models.CharField(max_length=32)
  32. addr = models.CharField(max_length=32)
  33.  
  34. def __str__(self) :
  35. return self.name

2、template 模版

  1. <!DOCTYPE html>
  2. <!-- saved from url=(0041)http://v3.bootcss.com/examples/dashboard/ -->
  3. <html lang="zh-CN">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6.  
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. <meta name="viewport" content="width=device-width, initial-scale=1">
  9. <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
  10. <meta name="description" content="">
  11. <meta name="author" content="">
  12. <link rel="icon" href="http://v3.bootcss.com/favicon.ico">
  13.  
  14. <title>图书管理系统</title>
  15.  
  16. <!-- Bootstrap core CSS -->
  17. <link href="/static/Dashboard_files/bootstrap.min.css" rel="stylesheet">
  18.  
  19. <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
  20. <link href="/static/Dashboard_files/ie10-viewport-bug-workaround.css" rel="stylesheet">
  21.  
  22. <!-- Custom styles for this template -->
  23. <link href="/static/Dashboard_files/dashboard.css" rel="stylesheet">
  24.  
  25. <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
  26. <!--[if lt IE 9]>
  27. <script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
  28. <script src="/static/Dashboard_files/ie-emulation-modes-warning.js"></script>
  29.  
  30. <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
  31. <!--[if lt IE 9]>
  32. <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
  33. <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
  34. <![endif]-->
  35.  
  36. <style>
  37. /*左侧菜单*/
  38. .head {
  39. margin: 1px -20px;
  40. line-height: 40px;
  41. text-align: center;
  42. }
  43. /*添加按钮*/
  44. .search {
  45. padding-bottom: 15px;
  46. }
  47. </style>
  48.  
  49. </head>
  50.  
  51. <body>
  52. <!--导航栏-->
  53. <nav class="navbar navbar-inverse navbar-fixed-top">
  54. <div class="container-fluid">
  55. <div class="navbar-header">
  56. <a class="navbar-brand" href="/index/">图书管理系统</a>
  57. </div>
  58. <div id="navbar" class="navbar-collapse collapse">
  59. <ul class="nav navbar-nav navbar-right">
  60. <li><a href="/index/">登录</a></li>
  61. <li><a href="/index/">注册</a></li>
  62. <li><a href="/index/">帮助</a></li>
  63. <li><a href="/index/">关于</a></li>
  64. </ul>
  65. </div>
  66. </div>
  67. </nav>
  68.  
  69. <!--左侧菜单 和 学生信息-->
  70. <div class="container-fluid">
  71. <div class="row">
  72. <!--左侧菜单-->
  73. <div class="col-sm-3 col-md-2 sidebar">
  74.  
  75. <div class="menu">
  76. <div class="head bg-primary">图书管理</div>
  77. <ul class="nav nav-sidebar">
  78. <li class=""><a href="/index/">&gt;&gt;&gt;查看图书</a>
  79. </li>
  80. <li><a href="/addbook/">&gt;&gt;&gt;添加图书</a></li>
  81. </ul>
  82. </div>
  83. <div class="menu">
  84. <div class="head bg-primary">作者管理</div>
  85. <ul class="nav nav-sidebar">
  86. <li><a href="/author/">&gt;&gt;&gt;查看作者</a></li>
  87. <li><a href="/addauthor/">&gt;&gt;&gt;添加作者</a></li>
  88. </ul>
  89. </div>
  90. <div class="menu">
  91. <div class="head bg-primary">出版社管理</div>
  92. <ul class="nav nav-sidebar">
  93. <li><a href="/publish/">&gt;&gt;&gt;查看出版社</a></li>
  94. <li><a href="/addpublish/">&gt;&gt;&gt;添加出版社</a></li>
  95. </ul>
  96. </div>
  97. </div>
  98. <!--学生信息(表格)-->
  99. <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
  100.  
  101. <div class="panel panel-primary">
  102. <div class="panel-heading">{% block info %}图书信息{% endblock info%}</div>
  103. <div class="panel-body">
  104. <!-- 搜索框-->
  105. {% block search %}
  106. <form class="form-inline" action="/searchbook/" method="post">
  107. {% csrf_token %}
  108. <div class="form-group search">
  109. <input type="text" class="form-control" placeholder="书名" name="book">
  110. <button class="btn btn-primary">搜索</button>
  111. </div>
  112. </form>
  113. {% endblock search %}
  114.  
  115. <!--内容-->
  116. <div class="table-responsive table-bordered">
  117. <table class="table table-striped" id="student">
  118. {% block content %}
  119. <thead>
  120. <div class="row">
  121. {% block th %}
  122. <tr>
  123. <th>编号</th>
  124. <th>书名</th>
  125. <th>作者</th>
  126. <th>出版日期</th>
  127. <th>价格</th>
  128. <th>出版社</th>
  129. <th>操作</th>
  130. </tr>
  131. {% endblock th %}
  132. </div>
  133. </thead>
  134. <tbody>
  135. {% block td %}
  136. {% for book_obj in bookList %}
  137. <tr>
  138. <td>{{ forloop.counter}}</td>
  139. <td>{{ book_obj.title }}</td>
  140. <td>
  141. {% for author in book_obj.authorlish.all %}
  142. {{ author.name }}
  143. {% endfor %}
  144. </td>
  145. <td>{{ book_obj.publishDate|date:"Y-m-d" }}</td>
  146. <td>{{ book_obj.prince }}</td>
  147. <td>{{ book_obj.publish.name }}</td>
  148. <td>
  149. <a href="/editbook/{{ book_obj.id }}"><button class="btn btn-info">编辑</button></a>
  150. <a href="/delbook/{{ book_obj.id }}"><button class="btn btn-danger">删除</button></a>
  151. </td>
  152. </tr>
  153. {% endfor %}
  154. {% endblock td %}
  155. </tbody>
  156. {% endblock content %}
  157. </table>
  158. </div>
  159. </div>
  160. </div>
  161.  
  162. </div>
  163. </div>
  164. </div>
  165.  
  166. <!-- Bootstrap core JavaScript
  167. ================================================== -->
  168. <!-- Placed at the end of the document so the pages load faster -->
  169. <script src="/static/Dashboard_files/jquery.min.js"></script>
  170. <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
  171. <script src="/static/Dashboard_files/bootstrap.min.js"></script>
  172. <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
  173. <script src="/static/Dashboard_files/holder.min.js"></script>
  174. <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
  175. <script src="/static/Dashboard_files/ie10-viewport-bug-workaround.js"></script>
  176.  
  177. <script>
  178. // 左侧菜单
  179. $(".head").on("click", function () {
  180. // 把自己 紧挨着的ul标签显示 removeClass("hide")
  181. $(this).next().slideToggle();
  182. // 兄弟标签 紧挨着的ul标签 隐藏 addClass("hide")
  183. $(this).parent().siblings().children("ul").slideUp();
  184. });
  185.  
  186. </script>
  187. </body>
  188. </html>

index.html

  1. {% extends "index.html" %}
  2.  
  3. {% block info %}
  4. 添加图书
  5. {% endblock info %}
  6.  
  7. {% block search %}
  8. <div class="row my-table-tool search">
  9. <div class="col-md-12">
  10. <a href="/index/"><button class="btn btn-primary">返回</button></a>
  11. </div>
  12. </div>
  13. {% endblock search %}
  14.  
  15. {% block th %}
  16. <tr>
  17. <th>书名</th>
  18. <th>作者</th>
  19. <th>出版日期</th>
  20. <th>价格</th>
  21. <th>出版社</th>
  22. <th>操作</th>
  23. </tr>
  24. {% endblock th %}
  25.  
  26. {% block td %}
  27. <form action="/addbook/" method="post">
  28. {% csrf_token %}
  29. <tr>
  30. <td><input type="text" name="title"></td>
  31. <td>
  32. <select name="author" id="" multiple>
  33. {% for author in authorList %}
  34. <option value="{{ author.name }}">{{ author.name }}</option>
  35. {% endfor %}
  36. </select>
  37. </td>
  38. <td><input type="date" name="publishDate"></td>
  39. <td><input type="text" name="prince"></td>
  40. <td>
  41. <select name="publish" id="">
  42. {% for publish in publishList %}
  43. <option value="{{ publish.name }}">{{ publish.name }}</option>
  44. {% endfor %}
  45. </select>
  46. </td>
  47. <td>
  48. <button class="btn btn-info">提交</button>
  49. </td>
  50. </tr>
  51. </form>
  52. {% endblock td %}

addbook.html

  1. {% extends "index.html" %}
  2.  
  3. {% block td %}
  4. {% for edit_obj in bookList %}
  5. {% if edit_obj.id == id %}
  6. <form action="/editbook/{{ edit_obj.id }}" method="post">
  7. {% csrf_token %}
  8. <tr>
  9. <td>{{ forloop.counter}}<input type="hidden" name="id" value="{{ edit_obj.id }}"></td>
  10. <td><input type="text" name="title" value="{{ edit_obj.title }}"></td>
  11. <td>
  12. <select name="author" id="" multiple>
  13. {% for author in authorList %}
  14. {% if author.name in edit_author %}
  15. <option selected value="{{ author.name }}">{{ author.name }}</option>
  16. {% else %}
  17. <option value="{{ author.name }}">{{ author.name }}</option>
  18. {% endif %}
  19. {% endfor %}
  20. </select>
  21. </td>
  22. <td><input type="date" name="publishDate" value="{{ edit_obj.publishDate|date:"Y-m-d" }}"></td>
  23. <td><input type="text" name="prince" value="{{ edit_obj.prince }}"></td>
  24. <td>
  25. <select name="publish" id="">
  26. {% for publish in publishList %}
  27. {% if publish.name == edit_obj.publish.name %}
  28. <option selected value="{{ publish.name }}">{{ publish.name }}</option>
  29. {% else %}
  30. <option value="{{ publish.name }}">{{ publish.name }}</option>
  31. {% endif %}
  32. {% endfor %}
  33. </select>
  34. </td>
  35. <td>
  36. <a href="/delbook/{{ edit_obj.id }}"><input type="button" class="btn btn-danger" value="删除"></a>
  37. <button class="btn btn-success">保存</button>
  38. </td>
  39. </tr>
  40. </form>
  41. {% else %}
  42. <tr>
  43. <td>{{ forloop.counter}}</td>
  44. <td>{{ edit_obj.title }}</td>
  45. <td>
  46. {% for author in edit_obj.authorlish.all %}
  47. {{ author.name }}
  48. {% endfor %}
  49. </td>
  50. <td>{{ edit_obj.publishDate|date:"Y-m-d" }}</td>
  51. <td>{{ edit_obj.prince }}</td>
  52. <td>{{ edit_obj.publish.name }}</td>
  53. <td>
  54. <a href="/editbook/{{ edit_obj.id }}"><button class="btn btn-info">编辑</button></a>
  55. <a href="/delbook/{{ edit_obj.id }}"><button class="btn btn-danger">删除</button></a>
  56. </td>
  57. </tr>
  58. {% endif %}
  59. {% endfor %}
  60. {% endblock td %}

editbook.html

  1. {% extends "index.html" %}
  2.  
  3. {% block info %}
  4. {{ booklist.first.title }}
  5. {% endblock info %}
  6.  
  7. {% block search %}
  8. <form class="form-inline" action="/searchbook/" method="post">
  9. {% csrf_token %}
  10. <div class="form-group search">
  11. <input type="text" class="form-control" placeholder="书名" name="book">
  12. <button class="btn btn-primary">搜索</button>
  13. <a href="/index/"><button class="btn btn-primary">返回</button></a>
  14. </div>
  15. {# <div class="row my-table-tool search">#}
  16. {# <div class="col-md-12">#}
  17. {# #}
  18. {# </div>#}
  19. {# </div>#}
  20. </form>
  21. {% endblock search %}
  22.  
  23. {% block th %}
  24. <tr>
  25. <th>编号</th>
  26. <th>书名</th>
  27. <th>作者</th>
  28. <th>出版日期</th>
  29. <th>价格</th>
  30. <th>出版社</th>
  31. <th>操作</th>
  32. </tr>
  33. {% endblock th %}
  34.  
  35. {% block td %}
  36. {% for book_obj in booklist %}
  37. <tr>
  38. <td>{{ forloop.counter}}</td>
  39. <td>{{ book_obj.title }}</td>
  40. <td>
  41. {% for author in book_obj.authorlish.all %}
  42. {{ author.name }}
  43. {% endfor %}
  44. </td>
  45. <td>{{ book_obj.publishDate|date:"Y-m-d" }}</td>
  46. <td>{{ book_obj.prince }}</td>
  47. <td>{{ book_obj.publish.name }}</td>
  48. <td>
  49. <a href="/editbook/{{ book_obj.id }}"><button class="btn btn-info">编辑</button></a>
  50. <a href="/delbook/{{ book_obj.id }}"><button class="btn btn-danger">删除</button></a>
  51. </td>
  52. </tr>
  53. {% endfor %}
  54. {% endblock td %}

searchbook.html

3、url 分发

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3.  
  4. from app01 import views
  5. urlpatterns = [
  6. url(r'^admin/', admin.site.urls),
  7. url(r'^index/', views.index),
  8. url(r'^delbook/(\d+)', views.delbook),
  9. url(r'^editbook/(\d+)', views.editbook),
  10. url(r'^addbook/', views.addbook),
  11. url(r'^searchbook/', views.searchbook),
  12.  
  13. url(r'^author/', views.author),
  14. url(r'^addauthor/', views.addauthor),
  15. url(r'^delauthor/(\d+)', views.delauthor),
  16. url(r'^editauthor/(\d+)', views.editauthor),
  17.  
  18. url(r'^publish/', views.publish),
  19. url(r'^addpublish/', views.addpublish),
  20. url(r'^delpublish/(\d+)', views.delpublish),
  21. url(r'^editpublish/(\d+)', views.editpublish),
  22. ]

4、views 视图函数

  1. from django.shortcuts import render,redirect,HttpResponse
  2.  
  3. # Create your views here.
  4.  
  5. from app01 import models
  6.  
  7. # 图书相关操作
  8. def index(request) :
  9. # 查看主页(图书)
  10. bookList = models.Book.objects.all()
  11. return render(request,"index.html",{"bookList":bookList})
  12.  
  13. def delbook(request,id) :
  14. # 删除图书
  15. models.Book.objects.filter(id=id).delete()
  16. return redirect("/index/")
  17.  
  18. def editbook(request,id) :
  19. # 点击保存POST提交
  20. if request.method == "POST" :
  21. # 提取数据
  22. id = request.POST.get("id")
  23. title = request.POST.get("title")
  24. author_name = request.POST.getlist("author")
  25. publishDate = request.POST.get("publishDate")
  26. prince = request.POST.get("prince")
  27. publish_name = request.POST.get("publish")
  28. # 出版社object
  29. publish_obj = models.Publish.objects.get(name=publish_name)
  30. # 移除旧关联
  31. book_obj = models.Book.objects.filter(id=id)[0]
  32. book_obj.authorlish.clear()
  33. # 更新图书表
  34. models.Book.objects.filter(id=id).update(title=title, publishDate=publishDate, prince=prince,publish_id=publish_obj)
  35. book_obj = models.Book.objects.filter(id=id)[0]
  36. # 添加新关联
  37. for i in author_name :
  38. print(i)
  39. obj = models.Author.objects.filter(name=i)[0]
  40. book_obj.authorlish.add(obj)
  41. return redirect("/index/")
  42.  
  43. # 图书、作者、出版社querySet
  44. bookList = models.Book.objects.all()
  45. authorList = models.Author.objects.all()
  46. publishList = models.Publish.objects.all()
  47. # 查看原作者
  48. author_name = models.Book.objects.filter(id=id).first().authorlish.all().values_list("name")
  49. edit_author = []
  50. for i in author_name :
  51. edit_author.append(i[0])
  52. return render(request,"editbook.html",{"bookList":bookList,"authorList":authorList,"publishList":publishList,"edit_author":edit_author,"id":int(id)})
  53.  
  54. def addbook(request) :
  55. # 添加图书页面点击提交
  56. if request.method == "POST" :
  57. # 提取添加数据
  58. title = request.POST.get("title")
  59. author = request.POST.getlist("author")
  60. publishDate = request.POST.get("publishDate")
  61. prince = request.POST.get("prince")
  62. publish = request.POST.get("publish")
  63. # 出版社object
  64. publish_obj = models.Publish.objects.filter(name=publish)[0]
  65. # 添加数据到数据库
  66. book_obj = models.Book.objects.create(title=title, publishDate=publishDate, prince=prince ,publish=publish_obj)
  67. # 多对多添加
  68. for i in author :
  69. obj = models.Author.objects.filter(name=i)[0]
  70. book_obj.authorlish.add(obj)
  71. return redirect("/index/")
  72.  
  73. # 作者与出版社querySet
  74. authorList = models.Author.objects.all()
  75. publishList = models.Publish.objects.all()
  76. return render(request,"addbook.html",{"authorList":authorList,"publishList":publishList})
  77.  
  78. def searchbook(request) :
  79. if request.method == "POST" :
  80. book = request.POST.get("book")
  81. print(book)
  82. booklist = models.Book.objects.filter(title__icontains = book)
  83. return render(request,"searchbook.html",{"booklist":booklist})

5、部分效果图

1)首页

2)添加图书

3)修改图书信息

4)搜索框搜索图书

66、django之模型层(model)--多表相关操作(图书管理小练习)的更多相关文章

  1. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  2. django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  3. django之模型层(model)--多表相关操作(图书管理小练习)

    前面几篇随笔的数据库增删改查操作都是在单表的操作上的,然而现实中不可能都是单表操作,更多的是多表操作,一对一,一对多,多对多的表结构才是我们经常需要处理的,本篇将带我们了解多表操作的一些相关操作.也会 ...

  4. 67、django之模型层(model)--查询补充及mookie

    本篇导航: F查询与Q查询 cookie 一.F查询与Q查询 1.以Book表为例 class Book(models.Model) : title = models.CharField(max_le ...

  5. django之模型层(model)--查询补充及cookie

    已经连续写了好几篇django的模型层(model)增删改查的随笔了,没篇大篇幅都是查询相关的操作,可以看出查询在数据的操作中是多么的重要,而本篇最后再补充一点关于关于查询的一些方法,模型层基本的操作 ...

  6. Django框架-模型层

    Django框架-模型层 一.单表查询之必知必会13条 1.时间字段中的两个关键性参数 create_time = models.DateField() # 年月日 create_time = mod ...

  7. 【Django】模型层说明

    [Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...

  8. Django基础模型层(77-78)

    jango框架之模型层(d77-78)一 单表操作: 1 mysql数据库:settings里配置  'default': {   # key值必须都是大写   'ENGINE': 'django.d ...

  9. python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)

    昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

随机推荐

  1. Spring第九篇【Spring与Hibernate整合】

    前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...

  2. linux(5)--补充(管道| / 重定向> / xargs)/find 与xargs结合使用/vi,grep,sed,awk(支持正则表达式的工具程序)

    本节中正则表达式的工具程序 grep,sed和awk是重点,也是难点!!! 先补充一下一. 管道| / 重定向> / xargs 如:1. 管道和重定向的区别:具体可以见 http://www. ...

  3. 检测Linux硬盘IO数据

    首先安装sysstat(有些系统会预装): apt install sysstat 然后使用命令: iostat -x -k 2 x选项用于显示和io有关的扩展数据 k某些使用block为单位的字段改 ...

  4. [python学习笔记] pyinstaller打包pyqt5程序无法运行

    问题 pyinstaller打包的pyqt5程序在部分电脑上会失败.用户截图提示下边错误日志 无法定位程序输入点 ucrtbase.terminate 于动态链接库 api-ms-win-crt-ru ...

  5. android自定义动画

    前一篇说了实现过程,这次来写一个自己简单实现的3d动画 先来属性声明配置,方便使用xml 文件来定制动画 <!-- 有些类型其实是没必要的,只是实例代码,为了更具有代表性 --> < ...

  6. Oculus关于Internal Error:OVR53225466报错解决方法

    安装Oculus过程中可能会出现Internal Error:OVR53225466报错提示,如附件所示: 解决方法:修改hosts文件 操作方法: (1)以管理员方式打开记事本: (2)打开C:\W ...

  7. Java伪代码描述《大道至简》第一章

    第一节 Begin //原始需求 惩山北之塞,出入之迂 //项目沟通的基本方式 聚室而谋曰 //项目目标 毕力平险,指通豫南,达于汉阴 //技术方案 扣石垦壤,箕畚运于渤海之尾 //技术人员和工程管理 ...

  8. Iframe刷新页面

    window.parent.frames["name"].location="url";

  9. Java历程-初学篇 Day07 循环结构2 for循环

    一,格式 for(赋值语句//为循环变量赋初值;条件语句//循环结构的循环条件;赋值语句//迭代,修改循环变量的值){ //循环体; } 二,简单举例 for(int i=1;i<=10;i++ ...

  10. Spring读书笔记——bean加载

    我们的日常开发几乎离不开Spring,他为我们的开发带来了很大的便捷,那么Spring框架是如何做到方便他人的呢.今天就来说说bean如何被加载加载. 我们在xml文件中写过太多类似这样的bean声明 ...