项目介绍:
本项目是一个实现出版社信息增删改查的Django项目,通过浏览器对不同URL的不同请求(POST、GET),来完成对出版社信息的展示、增加、删除、编辑/更新
创建Django项目,
创建并注册app,
指定template路径,
以上三项如果通过pycharm创建Django项目时就创建好了,就不用单独对app进行注册,也不用单独指定template路径了,pycahrm会默认做好这些操作)
注释CSRF校验,
创建数据库(booker),
配置数据库连接配置(booker数据库相关信息及连接db的模块)
以上内容实现请参阅《Django初识》两篇博文:
《Django初识初篇》
《Django初识续篇》
注意:
在实际项目中,可能数据库就是现成的,活着由DBA根据研发的要求设计好数据库结构并创建好数据库及表,而不再需要我们通过执行迁移脚本来创建数据库,那这个时候,我们只需要在models.py文件中定义好类、属性这些和数据库的对应关系即可,不需要再执行数据库迁移命令了
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=32)
# 制作迁移文件,表示之后要做的操作;会在migrations文件夹下生成一个0001_initial.py的文件
$ python3 manage.py makemigrations
# 执行具体的迁移动作
$ python3 manage.py migrate
# 数据库中会生成一个app01_publisher的表
之后可以在数据库中会生成一个app01_publisher的表
通过mysql数据库的客户端(命令行or图形化)连接数据库,然后通过sql语句或者直接图形化操作往表里插入测试数据
定义web访问的url与具体视图函数的对应关系
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publisher_list/',views.publisher_list)
通过OMR获取publisher表中所有对象,并返回给模版文件
from django.shortcuts import render
from app01 import models
# Create your views here.
# 展示出版社
def publisher_list(request):
# 查询所有的出版社对象
all_publishers = models.Publisher.objects.all()
# 将结果返回给页面
return render(request,'publisher_list.html',{'all_publishers':all_publishers})
接收试图函数传递的对象数据,循环展示到table标签中
<html lang="en">
<head>
<meta charset="UTF-8">
<title>出版社展示页面title>
head>
<body>
<table border="1">
<thead>
<tr>
<th>序号th>
<th>IDth>
<th>出版社名称th>
tr>
thead>
{# tbody中应用到了模版中循环的语法(因为无法确定数据库中到底有几行数据) #}
<tbody>
{% for publisher in all_publishers %}
<tr>
<td>{{ forloop.counter }}td> {# 是循环的计数,而不是数据库表中的id号 #}
<td>{{ publisher.id }}td> {# 是数据库中的id字段的内容 #}
<td>{{ publisher.name }}td>
tr>
{% endfor %}
tbody>
table>
body>
html>
补充模版文件语法知识点:
{% for i in object %}
...
{% endfor %}
<tbody>
{% for publisher in all_publishers %}
<tr>
<td>{{ forloop.counter }}td> {# 是循环的计数,而不是数据库表中的id号 #}
<td>{{ publisher.id }}td> {# 是数据库中的id字段的内容 #}
<td>{{ publisher.name }}td>
tr>
{% endfor %}
tbody>
forloop.counter # 取当前循环的次数
{{ 变量 }} # 双大括号中可进行变量操作
{% 语法语句 %} # 模版文件中在里面可以写其定义的语法,如for循环语句
定义web访问的url与具体视图函数的对应关系
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publisher_list/',views.publisher_list),
url(r'^publisher_add/',views.publisher_add),
]
通过OMR获取向publisher表中插入前端提交的出版社名称,并跳转至出版社展示页面
# 增加出版社
def publisher_add(request):
# POST请求方式的处理逻辑
if request.method == 'POST':
# 获取提交的数据
pub_name = request.POST.get('pub_name') # key名对应input标签中name字段的值
# 校验提交数据是否为空
if not pub_name:
return render(request,'publisher_add.html',{'error':'输入不能为空'})
print(pub_name,type(pub_name)) # 太空出版社
# 插入数据库
ret = models.Publisher.objects.create(name=pub_name) # 返回的是新插入的对象
print(ret,type(ret)) # Publisher object
# 跳转至展示页面
return redirect('/publisher_list/')
# 默认是get请求的处理逻辑
return render(request,'publisher_add.html')
接收试图函数传递的对象数据,循环展示到table标签中
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增出版社title>
head>
<body>
<h>新增出版社h>
<form action="" method="post">
<p>
出版社名称:<input type="text" name="pub_name"> <span>{{ error }}span>
p>
<p>
<button>提交button>
p>
form>
body>
html>
需要在publisher_list出版社的展示页面中,每一行记录的后面添加一个删除按钮,以完成数据的删除操作;其本质是一个a标签,用于发送请求的,然后根据发送请求的url对应到其路由信息指定的视图函数来处理
定义web访问的url与具体视图函数的对应关系
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publisher_list/',views.publisher_list),
url(r'^publisher_add/',views.publisher_add),
url(r'^publisher_del/',views.publisher_del),
]
通过URL传入的参数(pk),获取想要删除的数据,然后通过ORM模型进行删除,之后在跳转至publisher_list出版社展示页面
# 删除出版社
def publisher_del(request):
# 获取提交的数据
pk = request.GET.get('pk') # get中的pk是前端a标签中问号后面的键名
# 删除对应的数据
# models.Publisher.objects.get(pk=pk).delete() # 单个对象删除
models.Publisher.objects.filter(pk=pk).delete() # 删除所有满足条件的对象
# 跳转至展示页面
return redirect('/publisher_list/')
在原publisher_list.html的基础上,在table标签中新增“操作”列,具体包含了“删除”操作;
删除按钮,本质上是一个a标签,用于往后台指定的URL发送请求(同时带参指定要删除的数据),后台根据URL路由信息来找对应的视图函数来处理请求
<html lang="en">
<head>
<meta charset="UTF-8">
<title>出版社展示页面title>
head>
<body>
<table border="1">
<thead>
<tr>
<th>序号th>
<th>IDth>
<th>出版社名称th>
<th>操作th>
tr>
thead>
{# tbody中应用到了模版中循环的语法(因为无法确定数据库中到底有几行数据) #}
<tbody>
{% for publisher in all_publishers %}
<tr>
<td>{{ forloop.counter }}td> {# 是循环的计数,而不是数据库表中的id号 #}
<td>{{ publisher.id }}td> {# 是数据库中的id字段的内容 #}
<td>{{ publisher.name }}td>
<td>
<a href="/publisher_del/?pk={{ publisher.pk }}">删除a>
td>
tr>
{% endfor %}
tbody>
table>
body>
html>
web展示效果:
删除了id=3的出版社;可观察到:发送的请求,以及重定向的操作
定义web访问的url与具体视图函数的对应关系
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publisher_list/',views.publisher_list),
url(r'^publisher_add/',views.publisher_add),
url(r'^publisher_del/',views.publisher_del),
url(r'^publisher_edit/',views.publisher_edit),
]
接收前端发送过来的POST请求数据(带参数),然后根据接收到的参数,再通过ORM对数据库的数据进行编辑更新操作,然后再跳转至publisher_list出版社展示页面
# 编辑出版社
def publisher_edit(request):
# 获取提交的数据
pk = request.GET.get('pk')
# 查找要编辑的对象
obj = models.Publisher.objects.get(pk=pk)
if request.method == 'POST':
# 获取编辑后的数据
pub_name = request.POST.get('pub_name')
obj.name = pub_name # 重新对以上对象的name属性赋值(在内存中修改的)
obj.save() # 向数据库中提交更新(相当于持久化操作)
# 跳转到展示页面
return redirect('/publisher_list/')
return render(request,'publisher_edit.html',{'obj':obj})
接收试图函数传递的对象数据,循环展示到table标签中
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增出版社title>
head>
<body>
<h>新增出版社h>
<form action="" method="post">
{#<form action="/publisher_edit/" method="post">#}
<p>
{# <input type="hidden" name="id" value="{{ obj.pk }}">#}
出版社名称:<input type="text" name="pub_name" value="{{ obj.name }}"> <span>{{ error }}span>
p>
<p>
<button>提交button>
p>
form>
body>
html>
web展示效果:
此项目只是实现了最为基础的增删改查的操作,目的是在于让大家对Django项目的目录结构、文件作用、工作流程有一个初步的了解。
而对比实际项目,上述项目中有许多部分需要进一步优化,如路由的优化(命名分组、路由分发等),视图函数的优化(FBV、CBV),ORM的深度使用(多表查询、一对多、多对一等),视图的渲染及静态文件的补充(html+css+js等)…
可以理解为此项目是一个Django项目的基本骨架,要实际完成一个项目,仍需要对其进行脉络、肌肉、血液的填充。