做者的管理 html
出版社 书籍 做者数据库
一个出版社出版多个书籍 1对多django
书籍和做者的关系:一个做者写多本书,一本书能够是多个做者写。多对多app
1)建立一张表,表中多对多的数据关系。使用 多对多字段的方法ide
2)建立的这个类,会建立两个表,app_加类名(开头变小写),app_这个类名_另外一张表类名函数
3)这个类建立的表中没有多对多的字段,多对多的关系是以这张表表名加_id和另外一张表表名加_id两个字段合成的新的表,id主键自动生成oop
4)通常多对多字段关联的是有外键的那张表。url
url(r'^author_list/', views.author_list),
# 展现做者
for author in all_authors: print(author) print(author.pk) print(author.name) print(author.books,type(author.books)) # 关系管理对象 print(author.books.all(),type(author.books.all())) print('*'*30)
def author_list(request): # 查询全部的做者 all_authors = models.Author.objects.all() return render(request,'author_list.html',{'all_authors':all_authors})
点击这里可清空打印内容:spa
打印查看各个变量的含义设计
<class 'django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager'> 关系管理对象
经过关系管理对象.all()拿到全部关联的对象
由上可知:从做者表author.books.all()[0].title 得到了book表的书名,那么由author.books.all()[0].pub就能得到对应的一条出版社表的记录。从这张多对多关系的表中,获取到对应多对多关系另外一张表的多条记录,又由此能得到另外一张表的具备外键的对应的外键表记录,三表联系在一块儿了。
Book和Author多对多的关系。books是Author中你想要的对象跟Book关联的全部对象。books的做用是在Author和Book中建立一个中间的关系对象,放在第三张表中,再根据这个中间的关系来获取Book中关联的对象
外键和多对多关系区别:
外键是根据book.pub拿到的就是关联的外键对象(每行数据);而多对可能是Auther.books直接拿到的是一个关系管理对象,关系管理对象.all()才能拿到全部关联对象(每行数据)。
一个错误:一个函数重定向到本身这个函数会出现递归现象,达到递归上限,报错重定向次数过多,所以当这个函数想要从新返回到自身页面的时候用render,转到其它页面用render或者重定向
{% for author in all_authors %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td> {% for book in author.books.all %} {% if forloop.last %} 《{{ book.title }}》 {% else %} 《{{ book.title }}》、 {% endif %} {% endfor %} </td> </tr> {% endfor %}
将对象列表循环出来再取须要的字段,并添加书名号。
将循环出来的每一个内容用顿号隔开。
若是只是在后面加个逗号,那么最后那个都会显示逗号:
for循环中批量操做数据,经过添加判断实现知足条件的输出不一样内容,
# 新增出版社 def add_publisher(request): error = '' # 对请求方式进行判断 if request.method == 'POST': # 处理POST请求 # 获取到出版社的名称 publisher_name = request.POST.get('publisher_name') # 判断出版社名称是否有重复的 if models.Publisher.objects.filter(name=publisher_name): error = '出版社名称已存在' # 判断输入的值是否为空 if not publisher_name: error = '不能输入为空' if not error: # 使用ORM将数据插入到数据库中 obj = models.Publisher.objects.create(name=publisher_name) # 跳转到展现出版社的页面 return redirect('/publisher_list/') # 返回一个包含form表单的页面 return render(request, 'add_publisher.html', {'error': error})
author_obj = models.Author.objects.create(name=author_name) # 只插入book表中的内容 author_obj.books.set(books) # 设置做者和书籍多对多的关系
一个功能,一个url地址,一个函数,外加一个模板。每一个功能都是这样
添加做者,选择做者写的多个书籍,提交。实现多选功能:
添加做者:将提交的做者名字和做品获取到并写入数据库,而后重定向到做者展现页面
以下:在页面选中多个提交,可是get获取book的值只获取到一个,应该是选择的book列表才是咱们想要的,可是get只是获取到了最后一个数值
正确使用时getlist方法,获取select中多选的值
getlist获取到的类型是列表。多选中选中多个选项获取的值:
存入数据库:
1)先用input输入的做者名字建立做者表对象
2)再获取出来select选中多个关联选项
3)新建的做者对象.books得到关系管理对象,关系管理对象.set(要关联的多个外表的id列表)。由此,这个做者表对象set设置了和外表的多条记录的关系映射,并在第三张表中体现出来
【1】插入数据【2】设置它对多的关系
以下演示:
结果以下:表之接.东西,报错对象没有这个属性,这里是缺乏objects了,直接表.create会把它当作表的字段看待
正确结果:,注意create不要将给多对多的表明关系管理对象的设置值
而后再设置重定向到book_list页面
删除操做逻辑以下:
拿到要删除的数据id,而后查表找到对应数据进行删除再返回到展现页面
url设置,写函数,做者展现首页添加删除按钮:
删除成功;
books = request.POST.getlist('books') # 修改对象的数据 author_obj.name = name author_obj.save() # 多对多的关系 author_obj.books.set(books) # 每次从新设置
编辑和添加的html差很少,直接复制过来修改一下:
有多对多关系的表数据编辑:
1)url
2)函数
3)html
(1)做者展现页点击编辑a标签get请求并带有编辑的对象pk跳转到编辑页
(2)编辑页不是多对多关系的字段能够用输入框
(3)是多对多关系的须要使用多选框,多选框中是另外一个表中全部做品,被选中的即已是做者的做品 是与做者pk条件相等的做者表中关系管理对象的全部对象
逻辑关系以下:
# 编辑做者 def edit_author(request): # 查询编辑的做者对象 pk = request.GET.get('pk') author_obj = models.Author.objects.get(pk=pk) if request.method == 'POST': # 获取提交的数据 name = request.POST.get('author_name') books = request.POST.getlist('books') #注意是getlist,否则只能获取到一个数字 # 修改对象的数据 author_obj.name = name author_obj.save() # 多对多的关系 author_obj.books.set(books) # 每次从新设置 #不论是新增仍是修改都使用set就好了 # 重定向 return redirect('/author_list/') # 查询全部的书籍 all_books = models.Book.objects.all() #请求方式判断在前,由于POST中用不到这个 return render(request, 'edit_author.html', {'author_obj': author_obj, 'all_books': all_books})
每次编辑都是从新设置,也就是set以前会把和这个对象在关联表中关联的删掉并从新建立
class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 不在Author表中生产字段,生产第三张表
class AuthorBook(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) book = models.ForeignKey(Book, on_delete=models.CASCADE) date = models.DateField()
注销不用books
class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book',through='AuthorBook') # 不在Author表中生产字段,生产第三张表 class AuthorBook(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCA DE) book = models.ForeignKey(Book, on_delete=models.CASCADE) date = models.DateField()
1)第三种方式可使用 ManyToManyField 方法,经过第一个字符串参数指定和哪一个表关联;经过 through='自建第三张表'和自建第三张表联系起来,这样它自己不会建立第三张关联表了,而是以你写的第三张表的来做为它和它关联表之间的多对多关联关系。
2)这样的好处是我能够在django创建的关系表上添加字段(好比创建第三张关联表,图书id和做者id一一对应,可是我想要做者编写图书的时间,那么最好的地方就是放到这张表,而自建第三张表的方式才能给表添加字段;可是自建的表查询语句还要本身写,)
3)自建第三张表既能增长数据表字段,也能经过books.all()获取数据,可是不能使用set等某些方法,要想查数据仍是要本身写语句
4)自建第三张表是本身设置另外两张表的外键字段