Django - 图书管理系统
一、出版社增删改查
url
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^login/$', views.login), url(r'^index/$', views.index), url(r'^press_list/$', views.press_list), # 展示出版社 url(r'^add_press/$', views.add_press), # 添加出版社 url(r'^delete_press/$', views.delete_press), # 删除出版社 url(r'^edit_press/$', views.edit_press), # 编辑出版社 ]
models
from django.db import models class User(models.Model): id = models.AutoField(primary_key=True) # -> 创建一个自增的ID列作为主键 email = models.CharField(max_length=24) # -> varchar(32) pwd = models.CharField(max_length=16) # -> varchar(32) def __str__(self): return self.email # 出版社表 class Press(models.Model): id = models.AutoField(primary_key=True) # id主键 name = models.CharField(max_length=32) # 出版社名称 def __str__(self): return '<这是一个出版社对象,它的名字是:{}>'.format(self.name)
views
from django.shortcuts import render, HttpResponse, redirect from app01.models import User, Press def login(request): # print(request.GET) # print('-' * 120) error_msg = '' # 需要判断 # 根据请求的方法来做判断 if request.method == 'POST': # 如果是第二次来,表示填完了要给我发数据了 --> POST email = request.POST.get('email') pwd = request.POST.get('pwd') print(email, pwd) # if email == '1@1.com' and pwd == '123': # 从数据库查询有没有这个用户 # select * from app01_user where email='1@1.com' and pwd='123'; ret = User.objects.filter(email=email, pwd=pwd) print(type(ret[0])) print(ret[0].id, ret[0].email, ret[0].pwd) if ret: # 登录成功,跳转index return redirect('/index/') else: # 登录失败 # 提示用户邮箱或密码错误 error_msg = '邮箱或密码错误' # 如果你是第一次来,是跟我要一个登录页面用来填写数据的 --> GET return render(request, 'login.html', {'error_msg': error_msg}) def index(request): return render(request, 'index.html') # 出版社列表处理函数 def press_list(request): # 1. 去数据库查所有的出版社 ret = Press.objects.all().order_by('id') # print(ret) # print(ret[0]) # print(ret[0].name) # 2. 在HTML页面上展示出来 return render(request, 'press_list.html', {'kangchen': ret}) # 添加出版社的处理函数 def add_press(request): if request.method == 'POST': # 表示用户填写完了,要给我发数据 # 1. 取到用户填写的出版社数据 press_name = request.POST.get('name') # 2. 将数据添加到数据库中 Press.objects.create(name=press_name) # 3. 跳转到出版社列表页面 return redirect('/press_list/') # 1. 返回一个添加页面,让用户在上面填写新的出版社的信息 return render(request, 'add_press.html') # 删除出版社处理函数 def delete_press(request): # 1. 获取要删除的出版社ID delete_id = request.GET.get('id') print('-' * 120) print(delete_id) print('*' * 120) # 2. 根据id去数据库删除对应的数据行 Press.objects.filter(id=delete_id).delete() # 3. 让用户再去访问以下出版社列表页 return redirect('/press_list/') # 编辑出版社 def edit_press(request): # 1. 从URL中获取要编辑的出版社的id edit_id = request.GET.get('id') if request.method == 'POST': # 用户修改完出版社数据给我发过来了 # 1.取出用户编辑之后的数据 new_name = request.POST.get('name') # 2. 去数据库修改对应的数据 # 2.1 先找对应的数据:出版社对象 edit_press_obj = Press.objects.get(id=edit_id) # 2.2 修改出版社的名称 edit_press_obj.name = new_name # 2.3 将修改同步到数据库 edit_press_obj.save() # 3. 让用户再去访问出版社列表页 return redirect('/press_list/') # 2. 获取该出版社的信息 # ret = Press.objects.filter(id=edit_id) # -->[Press obj, ] # print(ret) ret = Press.objects.get(id=edit_id) # --> Press Obj, get()有且只能找到一个对象,否则就报错 print(ret) # 3. 在页面上展示出来 return render(request, 'edit_press.html', {'press_obj': ret})
templates:
1.press_list.html
<body> <a href="/add_author/">添加作者</a> <table border="1"> <thead> <tr> <th>序号</th> <th>作者id</th> <th>作者姓名</th> <th>作者作品</th> <th>操作</th> </tr> </thead> <tbody> {% for author in author_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.id }}</td> <td>{{ author.name }}</td> <td style="text-align: center"> {% for book in author.books.all %} {% if forloop.last %} 《{{ book.title }}》 {% else %} 《{{ book.title }}》, {% endif %} {% empty %} 暂无作品 {% endfor %} </td> <td> <a href="/delete_author/?kangchen={{ author.id }}&age=22">删除</a> <a href="/edit_author/?id={{ author.id }}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </body>
2.add_press.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>添加出版社</title> </head> <body> <form action="/add_press/" method="post"> <input type="text" name="name"> <input type="submit"> </form> </body> </html>
3.edit_press_list.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>编辑出版社</title> </head> <body> <h1>编辑出版社</h1> <form action="/edit_press/?id={{ press_obj.id }}" method="post"> <input type="text" name="name" value="{{ press_obj.name }}"> <input type="submit"> </form> </body> </html>
总结:
1. 图书管理系统之出版社的增删改查 1. 表结构设计 1. 出版社 id name 2. 作者 id name 3. 书 id title 出版社_id 4. 作者_书_关系表 id 书_id 作者_id 2. ORM版增删改查 1. ORM的语句 1. 类名.objects.all() --> 返回一个列表 2. 类名.objects.filter() --> 返回一个列表 3. 类名.objects.get() --> 返回一个对象 4. 类名.objects.create(name='') --> 创建一个对象,返回的就是刚创建的对象 5. 类名.objects.filter(id=).delete() --> 删除 6. obj = 类名.objects.get(id='') obj.name = '新值' --> 修改对象的属性(修改数据行某个字段的值) obj.save() --> 把修改同步到数据库 3. Django 模板语言 1. for循环 {% for i in ret %} {{ i }} {{ forloop.counter }} --> for循环从1开始计数 {{ forloop.counter0 }} --> for循环从0开始计数 {% endfor %}
二、书籍增删改查(一对多)
url
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^book_list/$', views.book_list), # 展示书籍 url(r'^add_book/$', views.add_book), # 添加书籍 url(r'^delete_book/$', views.delete_book), # 删除书籍 url(r'^edit_book/$', views.edit_book), # 编辑书籍 ]
models
from django.db import models # 出版社表 class Press(models.Model): id = models.AutoField(primary_key=True) # id主键 name = models.CharField(max_length=32) # 出版社名称 def __str__(self): return '<这是一个出版社对象,它的名字是:{}>'.format(self.name) # 书 class Book(models.Model): id = models.AutoField(primary_key=True) # 自增id主键 title = models.CharField(max_length=30) # 书名 # Django 1.11 默认就是级联删除, Django 2.0之后必须指定on_delete # to=关联的表名 press = models.ForeignKey(to='Press', on_delete=models.CASCADE)
views
# 书籍展示函数 def book_list(request): # 1. 查询所有的书籍数据 data = Book.objects.all() # 取到第一本书对象 # first_book = data[0] # print(first_book) # # 取到对象的title属性 # print(first_book.title) # # 取到对象的press属性 # print(first_book.press) # # 取到和我这本书关联的出版社的名字 # print(first_book.press.name) # # 取到和我这本书关联的出版社id # print(first_book.press_id) # # 连表查询到出版社id # print(first_book.press.id) # print('-' * 120) # 2. 在页面上展示出来 # 3. 返回完整的HTML页面 return render(request, 'book_list.html', {'data': data}) # 添加书籍的处理函数 def add_book(request): if request.method == 'POST': # 1. 取到用户填写的数据 book_title = request.POST.get('book_title') press_id = request.POST.get('press_id') # 2. 创建新的数据记录 # 基于外键对象的创建 # press_obj = Press.objects.get(id=press_id) # Book.objects.create(title=book_title, press=press_obj)# 这里注意是press= # 基于外键id值的创建 Book.objects.create(title=book_title, press_id=press_id)# 这里注意是press_id= # 3. 跳转到书籍列表页 return redirect('/book_list/') # 1. 返回一个页面,让用户填写书籍信息 # 因为书籍信息需要关联出版社 # 所以 在添加书籍的页面要把已经存在的出版社展示出来,让用户选择 press_data = Press.objects.all() return render(request, 'add_book.html', {'press_list': press_data}) # 删除书籍处理函数 def delete_book(request): # 1. 从URL中取到要删除的书籍的id值 delete_book_id = request.GET.get('id') # 2. 根据id值去数据库找到对应的数据,删除掉 Book.objects.filter(id=delete_book_id).delete() # 3. 跳转到书籍列表页面 # redirect实际做的事儿: # 给浏览器返回一个特殊的响应(命令) # 这个特殊的命令就是让浏览器再发一次请求,访问我指定的URL return render(request, 'delete_success.html') # return redirect('/book_list/') # 编辑书籍处理函数 def edit_book(request): # 1. 从URL中取到要编辑的书籍的id值 edit_book_id = request.GET.get('id') # 2. 根据id值找到要编辑的书籍对象 edit_book_obj = Book.objects.get(id=edit_book_id) if request.method == 'POST': # 1. 取到用户修改后的书籍名称和出版社信息 new_title = request.POST.get('book_title') new_press_id = request.POST.get('press_id') # 2. 修改书籍相应信息 edit_book_obj.title = new_title edit_book_obj.press_id = new_press_id # 3. 保存到数据库 edit_book_obj.save() # 4. 跳转到书籍列表页 return redirect('/book_list/') # 2.2 把所有的出版社查询出来 press_data = Press.objects.all() # 3. 在页面显示出当前书籍的信息,等待被编辑 return render( request, 'edit_book.html', {'book_obj': edit_book_obj, 'press_list': press_data} )
templates:
1.book_list.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>书籍列表页</title> </head> <body> <a href="/add_book/">添加书籍</a> <table border="1"> <thead> <tr> <th>序号</th> <th>书id</th> <th>书名称</th> <th>出版社</th> <th>操作</th> </tr> </thead> <tbody> {% for book in data %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> <td>{{ book.press.name }}</td> <td> <a href="/delete_book/?id={{ book.id }}">删除</a> <a href="/edit_book/?id={{ book.id }}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </body> </html>
2.add_book.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>添加书籍</title> </head> <body> <h1>添加书籍</h1> <form action="/add_book/" method="post"> <input type="text" name="book_title"> <select name="press_id"> {% for press in press_list %} <option value="{{ press.id }}">{{ press.name }}</option> {% endfor %} </select> <input type="submit"> </form> </body> </html>
3.edit_book.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>编辑书籍</title> </head> <body> <h1>编辑书籍</h1> <form action="" method="post"> <input type="text" name="book_title" value="{{ book_obj.title }}"> <select name="press_id" > {% for press in press_list %} {% if book_obj.press == press %} <option selected value="{{ press.id }}">{{ press.name }}</option> {% else %} <option value="{{ press.id }}">{{ press.name }}</option> {% endif %} {% endfor %} </select> <input type="submit"> </form> </body> </html>
总结:
书籍的增删改查 1. 查询 1. book_obj.press --> ORM层面封装的,返回的是和我这本书关联的出版社对象 2. book_obj.press_id --> 数据库中真正存在的字段,保存的是和我关联的出版社id值 2. 增加 1. 用select标签把已经存在的出版社在页面上展示出来 让用户去选择 使用的是:模板语言的for循环 3. 删除 1. 类似于上面出版社的操作 4. 编辑 1. 类似于于昨天的操作 2. 用select标签展示默认的出版社 1. Django模板语言中的if判断 {% if 条件 %} ... {% else %} ... {% endif %}
三、作者增删改查(多对多)
url
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^author_list/$', views.author_list), # 作者列表 url(r'^add_author/$', views.add_author), # 添加作者 url(r'^delete_author/$', views.delete_author), # 删除作者 url(r'^edit_author/$', views.edit_author), # 编辑作者 ]
models
from django.db import models # 出版社表 class Press(models.Model): id = models.AutoField(primary_key=True) # id主键 name = models.CharField(max_length=32) # 出版社名称 def __str__(self): return '<这是一个出版社对象,它的名字是:{}>'.format(self.name) # 书 class Book(models.Model): id = models.AutoField(primary_key=True) # 自增id主键 title = models.CharField(max_length=30) # 书名 price = models.IntegerField() # 价格 # Django 1.11 默认就是级联删除, Django 2.0之后必须指定on_delete # to=关联的表名 press = models.ForeignKey(to='Press', on_delete=models.CASCADE) # 作者 class Author(models.Model): id = models.AutoField(primary_key=True) # 自增id主键 name = models.CharField(max_length=32) # 作者名字 books = models.ManyToManyField(to='Book') # 只是ORM层面建立的一个多对多关系,不是作者表的一个字段 def __str__(self): return self.name
views
from django.shortcuts import render, HttpResponse, redirect from app01.models import User, Press, Book, Author def author_list(request): # 1. 去数据库查询到所有的作者 author_data = Author.objects.all() for author in author_data: print(author) # 取到每个作者出版的书籍 # print(author.books) # 是一个ORM提供的桥梁(工具),帮我找对应关系 print(author.books.all()) # 2. 在页面上展示出来 return render(request, 'author_list.html', {'author_list': author_data}) # 添加作者 def add_author(request): if request.method == 'POST': # 1. 取到用户填写的信息 new_author_name = request.POST.get('author_name') # book_ids = request.POST.get('books') # -->这个只能取到一个值 book_ids = request.POST.getlist('books') # print(new_author_name) # print(book_ids) print(request.POST.getlist('hobby')) print('-' * 120) # 2. 添加到数据库 # 2.1 创建新的作者 author_obj = Author.objects.create(name=new_author_name) # 2.2 创建新作者和书的对应关系 author_obj.books.add(*book_ids) # 参数是一个一个单独的书籍id值 # author_obj.books.set(book_ids) # 参数是书籍id值的列表 # 3. 跳转到作者列表页面 return redirect('/author_list/') # 1. 返回一个页面给用户,让用户填写作者信息 # 2. 获取所有的书籍信息 book_data = Book.objects.all() return render(request, 'add_author.html', {'book_list': book_data}) # 删除作者 def delete_author(request): # 1. 取到要删除的作者的id值 delete_author_id = request.GET.get('kangchen') age = request.GET.get('age') print(delete_author_id) print(age) # 2. 同过id找到数据,并删除 Author.objects.filter(id=delete_author_id).delete() # 3. 让用户再访问作者列表页面 return redirect('/author_list/') # 编辑作者 def edit_author(request): # 1. 取到要编辑的作者的id值 edit_author_id = request.GET.get('id') # 2. 找到要编辑的作者对象 edit_author_obj = Author.objects.get(id=edit_author_id) if request.method == 'POST': # 3. 拿到编辑之后的数据 new_author_name = request.POST.get('author_name') new_book_ids = request.POST.getlist('book_ids') # 4. 去数据库修改 # 4.1 修改作者表 edit_author_obj.name = new_author_name edit_author_obj.save() # 修改好的作者对象提交到数据库 # 4.2 修改作者和书的关系表 edit_author_obj.books.set(new_book_ids) # 5. 跳转到作者列表页面 return redirect('/author_list/') # 2.2 找到所有的书籍对象 book_data = Book.objects.all() # 3. 返回一个页面 return render(request, 'edit_author.html', {'author': edit_author_obj, 'book_list': book_data})
templates:
1.author_list.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>作者列表</title> </head> <body> <a href="/add_author/">添加作者</a> <table border="1"> <thead> <tr> <th>序号</th> <th>作者id</th> <th>作者姓名</th> <th>作者作品</th> <th>操作</th> </tr> </thead> <tbody> {% for author in author_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.id }}</td> <td>{{ author.name }}</td> <td style="text-align: center"> {% for book in author.books.all %} {% if forloop.last %} 《{{ book.title }}》 {% else %} 《{{ book.title }}》, {% endif %} {% empty %} 暂无作品 {% endfor %} </td> <td> <a href="/delete_author/?kangchen={{ author.id }}&age=22">删除</a> <a href="/edit_author/?id={{ author.id }}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </body> </html>
2.add_author.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>添加作者</title> </head> <body> <h1>添加作者</h1> <form action="" method="post"> <input type="text" name="author_name"> <select name="books" multiple="multiple"> {% for book in book_list %} <option value="{{ book.id }}">{{ book.title }}</option> {% endfor %} </select> </form> </body> </html>
3.edit_author.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>编辑作者</title> </head> <body> <h1>编辑作者</h1> <form action="" method="post"> <input type="text" name="author_name" value="{{ author.name }}"> <select name="book_ids" multiple> {% for book in book_list %} 如果 这本书 在 我这个作者关联的书籍列表里 {% if book in author.books.all %} <option selected value="{{ book.id }}">{{ book.title }}</option> {% else %} <option value="{{ book.id }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> <input type="submit"> </form> </body> </html>
总结:
1. 多对多关系 作者 <--> 书籍 1. 表结构设计 1. SQL版 -- 创建作者表 create table author( id int primary key auto_increment, name varchar(32) not null ); -- 创建作者和书的关系表 create table author2book( id int primary key auto_increment, author_id int not null, book_id int not null, constraint fk_author foreign key (author_id) references author(id) on delete cascade on update cascade, constraint fk_book foreign key (book_id) references book(id) on delete cascade on update cascade ); 2. ORM版 1. 第一版: 自己创建第三张表 2. 第二版 让ORM帮我们创建第三张表 models.ManyToManyField() 3. 第三版 待补充...(ORM进阶操作的时候) 2. 作者的增删改查 1. 查询 author_obj.books --> 得到的只是一个关联关系,并不能拿到数据 author_obj.books.all() --> 得到和我这个作者关联的所有书籍对象列表 2. 添加 1. add() 3. 删除 4. 编辑 1. 模板语言中 {% if book in author.books.all %} 2. ORM编辑多对多 1. 不能直接操作第三张关系表 2. 借助ORM给提供的方法 1. all() 2. add(id1,id2) 3. set([id1, id2]) 4. clear() 3. Django模板语言 1. for循环 1. forloop.last {% if forloop.last %} ... 2. empty {% for i in x %} ... {% empty %} ... {% endfor %}
幻想毫无价值,计划渺如尘埃,目标不可能达到。这一切的一切毫无意义——除非我们付诸行动。