1、图书管理系统
实现功能:
book单表的增删改查
增加图书界面
编辑图书界面
删除图书
先实现页面再弄基本逻辑
创建Django项目bookms
1、models.py
from django.db import models # Create your models here. class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32) # price总共8位数,2位小数 price=models.DecimalField(max_digits=8,decimal_places=2) pub_date = models.DateField() publish=models.CharField(max_length=32) def __str__(self): return self.title
2、在mysql数据库中创建数据库:book_single
3、settings配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'book_single', # 要连接的数据库,连接前需要创建好 'USER':'root', # 连接数据库的用户名 'PASSWORD':'123', # 连接数据库的密码 'HOST':'127.0.0.1', # 连接主机,默认本级 'PORT':3306 # 端口 默认3306 } }
4、项目名文件下的init,在里面写入:
import pymysql pymysql.install_as_MySQLdb()
5、在pycharm的Terminal执行
python manage.py makemigrations
python manage.py migrate
6、新建静态文件夹,把静态文件放其中,利用bootstrapweb框架来设计页面
src/href相对路径问题
同级目录直接写文件名称 <link rel="stylesheet" href="text.css">‘’ <script type="text/javascript" src="text.js"></script>
html中的相对路径:
../表示目录的上一级
例如:一个网站文件夹text里有HTML、JS、CSS....文件夹,HTML文件夹有个text.html, JS文件夹有个text.js, CSS文件夹中有个text.css。
则在text.html中引用text.js和text.css则可用这段代码:
<link rel="stylesheet" href="../CSS/text.css">
<script type="text/javascript" src="../JS/text.js"></script>
./表示同级目录
如:一个网站文件夹text里有HTML文件夹,text.js,text.css,HTML文件夹有个text.html,
则在text.html中引用text.js和text.css则可用这段代码:
<link rel="stylesheet" href="./text.css">
<script type="text/javascript" src="./text.js"></script>
重定向问题redirect
urls 分配的地址问题
Django中对于路径问题
可以考虑反向解析
第一站: url 路径匹配
django:url:路径指的是
http://ip+port+路径
单表原始版本:
from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('addbook/', views.addbook), path('books/', views.books),#查看 re_path(r'books/(\d+)/delete', views.delbook),#删除 delbook(request,id) re_path(r'books/(\d+)/change', views.changebook),#编辑 changebook(request,id) re_path(r'query/query', views.query),# 查询 ]
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01.models import Book def addbook(request): if request.method=='POST': title=request.POST.get('title') price=request.POST.get('price') pub_date=request.POST.get('pub_date') publish=request.POST.get('publish') if title == '' or price == '' or pub_date == '' or publish == '': return render(request, 'addbook.html', {'ret': '所有选项不能为空'}) # 添加数据 Book.objects.create(title=title,price=price,pub_date=pub_date,publish=publish) return redirect('/books/') return render(request,'addbook.html') def books(request): book_list=Book.objects.all()#[obj1,obj2] return render(request,'books.html',locals()) def delbook(request,id): Book.objects.filter(id=id).delete() # 删除成功后做重定向 # 方法一 #return render(request,'books.html') # 方法二 return redirect('/books/') def changebook(request,id): book_obj=Book.objects.filter(id=id).first() if request.method == 'POST': title = request.POST.get('title') price = request.POST.get('price') pub_date = request.POST.get('pub_date') publish = request.POST.get('publish') if title == '' or price == '' or pub_date == '' or publish == '': return render(request, 'addbook.html', {'ret': '所有选项不能为空'}) Book.objects.filter(id=id).update(title=title, price=price, pub_date=pub_date, publish=publish) return redirect('/books/') # 单个参数传递: # locals() 传递所有变量 return render(request,'changebook.html',{'book_obj':book_obj}) def query(request): # 1查询老男孩出版社出版过的价格大于200的书籍 ret=Book.objects.filter(publish='老男孩出版社',price__gt=200) # 2查询2017年8月出版的所有以py开头的书籍名称 ret2=Book.objects.filter(title__startswith='py',pub_date__year=2017,pub_date__month=8).values() # 3查询价格为50, 100或者150的所有书籍名称及其出版社名称 ret3=Book.objects.filter(price__in=[50,100,150]).values('title','publish') # 4查询价格在100到200之间的所有书籍名称及其价格 ret4=Book.objects.filter(price_range=[100,200]).values('title','price') # 5查询所有人民出版社出版的书籍的价格(从高到低排序,去重) ret5=Book.objects.filter(publish='人民出版社').values('price').order_by('-price').distinct() return HttpResponse('查询成功')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" type="text/css" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .container{ margin-top: 100px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <a href="/addbook/" class="btn btn-success pull-left ">添加书籍</a> <table class="table table-striped table-bordered table-hover"> <thead> <tr> <td>书籍名单</td> <td>价格</td> <td>出版日期</td> <td>出版社</td> <td><strong>删除操作</strong></td> <td><strong>编辑操作</strong></td> </tr> </thead> {##} {% for books in book_list %} <tr> <td>{{ books.title }}</td> <td>{{ books.price }}</td> <td>{{ books.pub_date|date:'Y-m-d' }}</td> <td>{{ books.publish }}</td> {# pk是主键的意思#} <td><a href="/books/{{ books.pk }}/delete" class="btn btn-danger" >删除</a></td> <td><a href="/books/{{ books.pk }}/change" class="btn btn-success" >编辑</a></td> </tr> {% endfor %} {# <tr class="active">...</tr>#} {# <tr class="success">...</tr>#} {# <tr class="warning">...</tr>#} {# <tr class="danger">...</tr>#} {# <tr class="info">...</tr>#} {##} {# <!-- On cells (`td` or `th`) -->#} {# <tr>#} {# <td class="active">...</td>#} {# <td class="success">...</td>#} {# <td class="warning">...</td>#} {# <td class="danger">...</td>#} {# <td class="info">...</td>#} {# </tr>#} </table> </div> </div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" type="text/css" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .container{ margin-top: 100px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <button class="btn btn-default center-block">添加书籍</button> <form action="" method="post"> {#这个标签用于跨站请求伪造保护#} {% csrf_token %} <div class="form-group"> <label for="title">书籍名称</label> <input type="text" class="form-control" id="title" name="title" > </div> <div class="form-group"> <label for="price">价格</label> <input type="number" class="form-control" id="price" name="price" > </div> <div class="form-group"> <label for="pub_date">出版时间</label> <input type="date" class="form-control" id="pub-date" name="pub_date" > </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" name="publish" > </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> </div> </div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" type="text/css" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .container{ margin-top: 100px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <button class="btn btn-default center-block">编辑书籍</button> <form action="" method="post"> {#这个标签用于跨站请求伪造保护#} {% csrf_token %} <div class="form-group"> <label for="title">书籍名称</label> <input type="text" class="form-control" id="title" name="title" value="{{ book_obj.title }}" > </div> <div class="form-group"> <label for="price">价格</label> <input type="number" class="form-control" id="price" name="price" value="{{ book_obj.price }}"> </div> <div class="form-group"> <label for="pub_date">出版时间</label> <input type="date" class="form-control" id="pub-date" name="pub_date" value="{{ book_obj.pub_date|date:'Y-m-d'}}"> </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" name="publish" value="{{ book_obj.publish }}"> </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> </div> </div> </div> </body> </html>
单表改进版本
融合继承等前面所学知识
1、路由分发知识点: 路由 主、从
urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^app01/',include('app01.urls')), ]
在app01项目下新建从 urls.py
from app01 import views
from django.urls import path,re_path
urlpatterns = [
path('addbook/', views.addbook),
path('books/', views.books),#查看
re_path(r'books/(\d+)/delete', views.delbook),#删除 delbook(request,id)
re_path(r'books/(\d+)/change', views.changebook),#编辑 changebook(request,id)
re_path(r'query/query', views.query),# 查询
]
2、views.py中的变化
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01.models import Book def addbook(request): if request.method=='POST': title=request.POST.get('title') price=request.POST.get('price') pub_date=request.POST.get('pub_date') publish=request.POST.get('publish') if title == '' or price == '' or pub_date == '' or publish == '': return render(request, 'addbook.html', {'ret': '所有选项不能为空'}) # 添加数据 Book.objects.create(title=title,price=price,pub_date=pub_date,publish=publish) return redirect('/app01/books/') return render(request,'addbook.html') def books(request): book_list=Book.objects.all()#[obj1,obj2] return render(request,'books.html',locals()) def delbook(request,id): Book.objects.filter(id=id).delete() # 删除成功后做重定向 # 方法一 #return render(request,'books.html') # 方法二 return redirect('/app01/books/') def changebook(request,id): book_obj=Book.objects.filter(id=id).first() if request.method == 'POST': title = request.POST.get('title') price = request.POST.get('price') pub_date = request.POST.get('pub_date') publish = request.POST.get('publish') if title == '' or price == '' or pub_date == '' or publish == '': return render(request, 'addbook.html', {'ret': '所有选项不能为空'}) Book.objects.filter(id=id).update(title=title, price=price, pub_date=pub_date, publish=publish) return redirect('/app01/books/') # 单个参数传递: # locals() 传递所有变量 return render(request,'changebook.html',{'book_obj':book_obj}) def query(request): # 1查询老男孩出版社出版过的价格大于200的书籍 ret=Book.objects.filter(publish='老男孩出版社',price__gt=200) # 2查询2017年8月出版的所有以py开头的书籍名称 ret2=Book.objects.filter(title__startswith='py',pub_date__year=2017,pub_date__month=8).values() # 3查询价格为50, 100或者150的所有书籍名称及其出版社名称 ret3=Book.objects.filter(price__in=[50,100,150]).values('title','publish') # 4查询价格在100到200之间的所有书籍名称及其价格 ret4=Book.objects.filter(price_range=[100,200]).values('title','price') # 5查询所有人民出版社出版的书籍的价格(从高到低排序,去重) ret5=Book.objects.filter(publish='人民出版社').values('price').order_by('-price').distinct() return HttpResponse('查询成功')
分析:添加过程
点击查询界面的添加书籍
路径分发到views.py中的addbook,
登陆和点击按钮都是get请求
def addbook(request):
if request.method=='POST': title=request.POST.get('title') price=request.POST.get('price') pub_date=request.POST.get('pub_date') publish=request.POST.get('publish') if title == '' or price == '' or pub_date == '' or publish == '': return render(request, 'addbook.html', {'ret': '所有选项不能为空'}) # 添加数据 Book.objects.create(title=title,price=price,pub_date=pub_date,publish=publish) return redirect('/app01/books/')
点击 添加书籍 是get请求:出现addbook.html表现出来的页面
return render(request,'addbook.html')
对于‘addbook.html’存在疑问,看 render的第二个参数和项目中的templates就很清楚了
1、填写数据,当数据完整时点击提交按钮是POST请求,addbook.html表单里面规定method='post'
form 中 action:'''' ,为空默认当前地址appo1/addbook.html
路由分发后,回到views.py def addbook()函数下进行判断
数据不为空则创建数据,数据为空重新填写并提醒
{# url 控制器 action 默认 当前 反向解析 模板语法{{ }} 和{% %} 两种 #} <form action="{% url 'Log' %}" method="post">
单个参数传递
return render(request, 'index.html', {'name': name})
在index.html文件中
{{ name }}表达出来
传递所有参数:
return render(request,'index.html',locals())
action='url',规定提交表单向何处发送表单数据
target不写默认在当前页打开
3、建立一个base.html用于给其他html继承
其中标签,css属性
这里的名称不同,子模块继承也要写想要的名称,一一对应的关系
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> {% block title %} <title>base</title> {% endblock title %} <!-- Bootstrap --> <link href="/static/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 --> <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 --> <!--[if lt IE 9]> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> <link rel="stylesheet" href="/static/base.css"> <style type="text/css"> {% block css %} .container{ margin-top: 100px; } {% endblock %} </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> {% block con %} {% endblock %} </div> </div> </div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="/static/jquery-3.2.1.min.js"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </body> </html>
{% extends 'base.html' %} {% block css %} {{ block.super }} {% endblock %} {% block con %} {# 路由分发#} <a href="/app01/addbook/" class="btn btn-success pull-left ">添加书籍</a> <table class="table table-striped table-bordered table-hover"> <thead> <tr> <td>书籍名单</td> <td>价格</td> <td>出版日期</td> <td>出版社</td> <td><strong>删除操作</strong></td> <td><strong>编辑操作</strong></td> </tr> </thead> {##} {% for books in book_list %} <tr> <td>{{ books.title }}</td> <td>{{ books.price }}</td> <td>{{ books.pub_date|date:'Y-m-d' }}</td> <td>{{ books.publish }}</td> {# pk是主键的意思#} <td><a href="/app01/books/{{ books.pk }}/delete" class="btn btn-danger" >删除</a></td> <td><a href="/app01/books/{{ books.pk }}/change" class="btn btn-success" >编辑</a></td> </tr> {% endfor %} </table> {% endblock %}
{% extends 'base.html' %} {% block css %} {{ block.super }} {% endblock %} {% block con %} <button class="btn btn-default center-block">添加书籍</button> <form action="" method="post"> {#这个标签用于跨站请求伪造保护#} {% csrf_token %} <div class="form-group"> <label for="title">书籍名称</label> <input type="text" class="form-control" id="title" name="title" > </div> <div class="form-group"> <label for="price">价格</label> <input type="number" class="form-control" id="price" name="price" > </div> <div class="form-group"> <label for="pub_date">出版时间</label> <input type="date" class="form-control" id="pub-date" name="pub_date" > </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" name="publish" > </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> <h3> <p style="color: red;">{{ ret }}</p> </h3> {% endblock %}
{% extends 'base.html' %} {% block css %} {{ block.super }} {% endblock %} {% block con %} <button class="btn btn-default center-block">编辑书籍</button> <form action="" method="post"> {#这个标签用于跨站请求伪造保护#} {% csrf_token %} <div class="form-group"> <label for="title">书籍名称</label> <input type="text" class="form-control" id="title" name="title" value="{{ book_obj.title }}" > </div> <div class="form-group"> <label for="price">价格</label> <input type="number" class="form-control" id="price" name="price" value="{{ book_obj.price }}"> </div> <div class="form-group"> <label for="pub_date">出版时间</label> <input type="date" class="form-control" id="pub-date" name="pub_date" value="{{ book_obj.pub_date|date:'Y-m-d'}}"> </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" name="publish" value="{{ book_obj.publish }}"> </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> <h3> <p style="color: red;">{{ ret }}</p> </h3> {% endblock %}
查询操作练习
1
查询老男孩出版社出版过的价格大于
200
的书籍
2
查询
2017
年
8
月出版的所有以py开头的书籍名称
3
查询价格为
50
,
100
或者
150
的所有书籍名称及其出版社名称
4
查询价格在
100
到
200
之间的所有书籍名称及其价格
5
查询所有人民出版社出版的书籍的价格(从高到低排序,去重)
# 1查询老男孩出版社出版过的价格大于200的书籍 ret=Book.objects.filter(publish='老男孩出版社',price__gt=200) # 2查询2017年8月出版的所有以py开头的书籍名称 ret2=Book.objects.filter(title__startswith='py',pub_date__year=2017,pub_date__month=8).values() # 3查询价格为50, 100或者150的所有书籍名称及其出版社名称 ret3=Book.objects.filter(price__in=[50,100,150]).values('title','publish') # 4查询价格在100到200之间的所有书籍名称及其价格 ret4=Book.objects.filter(price_range=[100,200]).values('title','price') # 5查询所有人民出版社出版的书籍的价格(从高到低排序,去重) ret5=Book.objects.filter(publish='人民出版社').values('price').distinct().order_by('-price')