Django框架(六)---- app部件协作
该实例
基于:Python3.6,Django-1.11,MySQL-5.7,(Windows)
实现:访问Django服务,进行数据库信息的增删改功能
前奏:1、创建Django项目:django-admin startproject demo
2、创建app:python manage.py startapp mytest (manage.py文件一级的目录下)
3、创建templates目录 (manage.py文件一级的目录下),在templates目录下,创建mytest目录
4、于settings.py文件内设置:(1) 于INSTALLED_APPS中添加mytest
(2)TEMPLATES中的DIRS添加:os.path.join(BASE_DIR, 'templates')
(3) DATABASE中,删除默认sqlite3设置,添加mysql设置
5、复制一份demo/urls.py到mytest中
6、在demo/__init__.py文件中添加代码:import pymysql
pymysql.install_as_MySQLdb()
7、于demo/urls.py文件中的urlpatterns中添加:url(r'^mytest/', include('mytest.urls'))
8、创建空的数据库,数据库名根据第四步中的DATABASE
9、创建数据库表,建表语句:
主菜:
1、根据之前创建的数据库表,在models.py中创建model类,其中的三个属性和数据库表的字段的数据类型保持一致:
1 class Users(models.Model):
2 name = models.CharField(max_length=32)
3 age = models.IntegerField(default=20)
4 phone = models.CharField(max_length=16)
2、在views.py视图文件中,创建所需要的视图函数,先起个名字,pass:
1 from .models import Users
2
3 def user(request): # 展示数据表中的数据
4 pass
5
6 def adduser(request): # 预备跳转到添加数据的模板Html
7 pass
8
9 def insertuser(request): # 将add.html模板传来的数据添加进入数据库表
10 pass
11
12 def deluser(request): # 删除数据
13 pass
14
15 def edituser(request): # 跳转到edit.html模板,修改
16 pass
17
18 def updateuser(request): # 将edit.html模板传来的修改过的数据进行数据库表更新
19 pass
3、在mytest/urls.py子路由文件中,设置其中每个功能规定的url规则,以及指向对应的视图:
1 from django.conf.urls import url
2
3 from . import views
4
5 app_name = 'mytest'
6 urlpatterns = [
7 url(r'^$', views.user, name='user'), # 展示
8 url(r'^user/add$', views.adduser, name='user_add'), # 添加
9 url(r'^user/insert$', views.insertuser, name='user_insert'), # 提交添加
10 url(r'^user/del/(?P<userid>[0-9]+)$', views.deluser, name='user_del'), # 删除
11 url(r'^user/edit/(?P<userid>[0-9]+)$', views.edituser, name='user_edit'), # 修改
12 url(r'^user/update$', views.updateuser, name='user_update'), # 提交修改
13 ]
解析:1、app_name:本例中实际只有一个应用程序mytest,实际开发中会有多个app,可以在这里设置app_name进行区分相应的视图
2、在删除和修改的url()中,正则中有(?P<userid>[0-9]+),?P<userid>代表指定的deluser和edituser除了request参数,还有一个叫做userid的参数
3、每个url()中,都有一个叫做name的参数,唯一不重复,这些name参数值,会在视图模板中用到,目的是为了项目开发后,修改前面正则匹配规则后,可以作用于项目全局
4、开始进行模板创建以及view函数的构建:
(1)、现在需要一个模板,模板展示mytest app对应的数据库表中的数据信息:
首先,先将views.user函数构建完成,实现功能:从数据库表中读取所有数据,并且将数据传送给相对应的user.html模板
1 from django.shortcuts import render
2 from .models import Users
3
4 def user(request):
5 lists = Users.objects.all()
6 context = {"user_list": lists}
7 return render(request, "mytest/user.html", context)
分析:上述代码中,需要提前导入models模块中的Users类,用于创建Users.objects这个数据库表映射
Users.objects.all():表示获取数据库表中的所有数据
context:为传送给模板的数据,必须是一个字典类型,"user_list"这个key值,会在模板中使用到
view视图函数必须返回一个HttpResponse,这里没有用到Django.http.HttpResponse,用到了Django提供的快捷方式render()函数
render()函数接收接收请求对象作为第一个参数,模板名称作为第二个参数,字典作为可选的第三个参数。
然后创建一个简单的模板user.html在templates/mytest目录下:
1 <center>
2 {% include "mytest/menu.html" %}
3 <table width="500" border="1">
4 <tr>
5 <th>ID</th>
6 <th>Name</th>
7 <th>Age</th>
8 <th>Phone</th>
9 <th>edit/del</th>
10 </tr>
11 {% for v in user_list %}
12 <tr>
13 <td>{{ v.id }}</td>
14 <td>{{ v.name }}</td>
15 <td>{{ v.age }}</td>
16 <td>{{ v.phone }}</td>
17 <td>
18 <a href="{% url 'mytest:user_edit' v.id %}">edit</a> |
19 <a href="{% url 'mytest:user_del' v.id %}">del</a>
20 </td>
21 </tr>
22 {% endfor %}
23 </table>
24 </center>
这里显示在html的body中的代码:
解析:可以看到代码实现了一个table标签,里面通过for遍历由上面views.user视图传递过来的user_list,取出其中的四个数据,填充进入tr的td中
每行预留了修改和删除数据的按钮,这个后续会进行补充修改
第2行的{% include "mytest/menu.html" %} 后续会讲到
在数据库表中输入一些数据,运行Django服务,浏览器输入 127.0.0.1:8000/mytest,可以看到数据库表中的数据:
(2)、现在需要填加 向数据库表中添加数据的功能:
首先,补充完views.add函数,目的是为了在点击按钮后,跳转到add.html模板中:
1 def adduser(request):
2 return render(request, "mytest/add.html")
然后创建add.html模板,代码为在add.html中的body的内容:
1 <center>
2 {% include "mytest/menu.html" %}
3 <form action="{% url 'mytest:user_insert' %}" method="POST">
4 {% csrf_token %}
5 <table width="320">
6 <tr>
7 <td>Name: </td>
8 <td><input type="text" name="name"></td>
9 </tr>
10 <tr>
11 <td>Age: </td>
12 <td><input type="text" name="age"></td>
13 </tr>
14 <tr>
15 <td>Phone: </td>
16 <td><input type="text" name="phone"></td>
17 </tr>
18 <tr>
19 <td colspan="2">
20 <input type="submit">
21 <input type="reset">
22 </td>
23 </tr>
24 </table>
25 </form>
26 </center>
这里创建了一个信息输入表,以POST方法,提交其中的数据到子路由中的user_insert所指向的视图中去进行后续处理;
这里需要注意的是第4行的代码,因为本页的数据是按照POST方式传送的,必须要有一个类似令牌的数据和我们的User数据一同传送过去,否则Django会拒绝你的传送,
究其原因,是为了数据的安全,由中间件django.middleware.csrf.CsrfViewMiddleware控制,可以在settings.py文件中的中间件设置中找到。
在第3行的action,它的值表示,将form表单中的数据提交给name="user_insert"的子路由urls.py中的url,因为之前在子路由中标明了app_name="mytest",所以这里使用mytest:user_insert写法
(3)、上面两个模板中,都带一个 {% include "mytest/menu.html" %}
在书写模板时,有些功能部件可以单独摘取出来,写成其他的html,之后再需要这个功能的时候,可以导入代码中,避免每个模板都要重写这写部件;
例如在本例中,我们在页面的上面构建两个按钮,一个是展示所有数据,一个就是添加数据,这两个构建需要贯穿全部模板,那么就可以创建一个menu.html文件
1 <a href="{% url 'mytest:user' %}">show users</a> |
2 <a href="{% url 'mytest:user_add' %}">add user</a>
然后,在每个模板调用这个menu.html时,使用{% include " " %}语法在合适的位置导入即可
(4)、在上面的add.html模板中,填写需要添加的User信息,点击提交按钮,会以POST方法将数据传送给name="user_insert"的views.insertuser视图,进行存储到数据库
首先将views.insert_user函数补充完整
1 def insertuser(request):
2 try:
3 ob = Users()
4 ob.name = request.POST.get("name", "")
5 ob.age = request.POST.get("age", 20)
6 ob.phone = request.POST.get("phone", "")
7 ob.save()
8 context = {
9 "info": "Save OK"
10 }
11 except:
12 context = {
13 "info": "Error"
14 }
15 return render(request, "mytest/info.html", context)
解析:首先建立一个Users对象,然后进行赋值,因为是以POST方法传送到insetuser函数的,所以需要用request.POST,然后获取POST中的value值,第二个参数代表默认,没有对应值的时候,使用默认值
这里没有数据库表的id字段值,因为它是自增主键,存储时会自动生成
想要存储进数据库表,还需要调用save()函数,这条数据才会真正存储到表中
我们可以创建一个info.html模块,传递保存成功或者错误的文本,当在add.html点击提交时,经过后台操作,反馈是否成功的信息
(5)、在浏览器操作删除表中的数据,就目前数据库表,删除一个元素,需要利用它的id字段值,那么views.deluser视图函数:
1 from django.shortcuts import render, redirect
2 from django.core.urlresolvers import reverse
3
4 def deluser(request, userid):
5 ob = Users.objects.get(id=userid)
6 ob.delete()
7 return redirect(reverse("mytest:user"))
在调用deluser函数时,需要传递一个id字段值,之前在子路由中使用了 ?<userid> ,所以此处的id字段值使用userid作为参数名
使用get()方法,得到userid对应的这条数据后,使用delete()进行数据库表的数据删除操作
此时,删除成功后,可以跳转到user.html模板,看到删除一条数据后剩余的数据,
但是如果使用render(request, "mytest/user.html"),则会产生一个现象,页面显示的是user.html模板内容,但是此时的url显示的是127.0.0.1:8000/mytest/del/...,不对应
所以此处使用Django的重定向,使得删除数据后,url为 127.0.0.1:8000/mytest
之前在user.html模板中,预留了文本值为del的a标签的href属性,到这里就可以设置成:{% url 'mytest:user_del' v.id %}
这里传入一条数据的id值 v.id到del_user视图函数
(6)、在浏览器修改表中的数据,需要一个edit.html模板
1 <center>
2 {% include "mytest/menu.html" %}
3 <form action="{% url 'mytest:user_update' %}" method="POST">
4 {% csrf_token %}
5 <input type="hidden" name="id" value="{{ user.id }}">
6 <table width="320">
7 <tr>
8 <td>Name: </td>
9 <td><input type="text" name="name" value="{{ user.name }}"></td>
10 </tr>
11 <tr>
12 <td>Age: </td>
13 <td><input type="text" name="age" value="{{ user.age }}"></td>
14 </tr>
15 <tr>
16 <td>Phone: </td>
17 <td><input type="text" name="phone" value="{{ user.phone }}"></td>
18 </tr>
19 <tr>
20 <td colspan="2">
21 <input type="submit">
22 <input type="reset">
23 </td>
24 </tr>
25 </table>
26 </form>
27 </center>
解析:这个页面依旧使用POST方法传送数据,到views.updateuser视图中进行修改后的数据处理;
在3个input标签中,分别设置value属性,将原本的数据值显示出来,其中使用了user代表传送过来的数据
在form表单中,有一条隐藏的input,设置其中的value为原数据的id,这个值无法改动,但是需要这个值和其他三个修改后的值一同传送给views.updateuser视图函数
现在补充完整views.edituser视图函数:
1 def edituser(request, userid):
2 ob = Users.objects.get(id=userid)
3 if ob is None:
4 return HttpResponse("No find info")
5 context = {"user": ob}
6 return render(request, "mytest/edit.html", context)
如deluser视图函数一样,需要传入一个id值,将查询到的数据信息,组成一个字典,key值就是在edit.html模板中表示原数据的名称,将查询到的数据信息传送给edit.html模板
(7)、第6步中,将修改后的数据信息以POST方法传递给views.updateuser视图函数,所以这里需要补齐updateuser():
1 def updateuser(request):
2 try:
3 ob = Users.objects.get(id=request.POST.get("id"))
4 ob.name = request.POST.get("name")
5 ob.age = request.POST.get("age")
6 ob.phone = request.POST.get("phone")
7 ob.save()
8 context = {
9 "info": "Edit OK"
10 }
11 except:
12 context = {
13 "info": "Error"
14 }
15 return render(request, "mytest/info.html", context)
解析:首先我们根据传送过来的request.POST中的数据id值,首先查找出在数据库表中的对应的数据,然后将request.POST中的name,age,phone分别赋值给这个原数据,并且保存
最后根据是否成功,跳转到info.html
至此:一个简单的应用,浏览器操作数据库数据交互。一整套下来,可以理解app部件之间的相互关系,数据的传递等等。。
如找出错误,请在下面写留言指正,谢谢~
相关查找,可以使用这个 Django-1.10中文文档来查看