在说明django模型之前,首先来说明一下django的生命周期,也就是一个请求到达django是如何处理的。【暂时不包含中间件】
浏览器的请求---->到达django中的urls中找到对应的映射------>到达视图层(返回的是html页面,html页面来自模板(templates)中的前端文件)---->前端中若是有数据需要来自后端的服务器,则需要模型(model),数据处理完毕之后通过return函数返回给客户端。【不太准确,一个简单的mvc模型】
通过以上描述,我们知道,模型的主要作用就是用来和后端交互。django是用python写的,因此在交互时可以使用python的orm(对象关系映射)来完成操作,但是django自带的model已经非常完善了,因此我们不需要在使用其他的orm。
为了更直观的显示model的作用,首先我们使用python的orm来完成一个前后端交互的实例。
测试环境: python2.6, django1.10.8
在python3中需要使用pymysql代替MySQldb.
基于前端的显示(前端代码如下),我们需要创建如下的表,可以使用python的MySQLdb连接mysql服务器使用orm映射创建,但是这里为了方便直接在MySQL上创建,如下:
这里的html代码和css代码分开了写,需要在html中引入css代码!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <link rel="stylesheet" type="text/css" href="/static/main_page.css"> </head> <body> <div class="out-border"> <div class="meg1"> <span class="sp1">留言板</span> </div> <form action="/main/" method="post"> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 用户名 </span > <input type="text" name="user" class="user_meta"> </div> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 密码 </span> <input type="password" name="pwd" class="user_meta"> </div > <div class="itemc"> <span class="left_content"> <b class="star">*</b> 邮箱 </span> <input type="email" name="email" class="user_meta"> </div> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 留言 </span> <!-- textarea两个标签不要有空格,不然光标不会放到第一个位置--> <textarea name="message" id="Message" cols="30" rows="10"></textarea> </div> <input type="submit" class="betn_megSubmit" value="提交留言"> {% csrf_token %} </form> </div> </body> </html>
.out-border{ 500px; height: 500px; margin-top: 50px; margin-left: 30%; border: solid #faf8f9 1px; border-radius: 5px; } .meg1{ background-color: #fa6104; height: 60px; border-radius: 5px; } .sp1{ float: left; color: whitesmoke; margin-top: 13px; font-size: 25px; margin-left: 213px; letter-spacing: 10px; } .user_meta{ border-radius: 5px; background-color: #faf8f9; padding: 5px; 202px; font-size: 14px; } .star{ color: #dd2218; } .left_content{ display: block; float: left; 128px; margin-right: 10px; text-align: right; line-height: 30px; font-size: 16px; color: #333333; } .itemc{ margin-top: 30px; } #Message{ font: 14px "Microsoft Yahei"; padding: 5px; color: #666; resize: none; height: 148px; 300px; border-radius: 5px; background-color: #faf8f9; } .betn_megSubmit{ display: block; 180px; height: 40px; border: 1px solid #fa6104; background: #fa6104; color: #fff; border-radius: 5px; line-height: 30px; float: left; font-size: 18px; margin-left: 139px; _margin-left: 37px; margin-right: 30px; cursor: pointer; margin-top: 15px; }
如果分开存放,需要在settings中引入静态文件目录:
STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <style> .out-border{ 500px; height: 500px; margin-top: 50px; margin-left: 30%; border: solid #faf8f9 1px; border-radius: 5px; } .meg1{ background-color: #fa6104; height: 60px; border-radius: 5px; } .sp1{ float: left; color: whitesmoke; margin-top: 13px; font-size: 25px; margin-left: 213px; letter-spacing: 10px; font-family: Microsoft Yahei; } .user_meta{ border-radius: 5px; background-color: #faf8f9; padding: 5px; 202px; font-size: 14px; } .star{ color: #dd2218; } .left_content{ display: block; float: left; 128px; margin-right: 10px; text-align: right; line-height: 30px; font-size: 16px; color: #333333; } .itemc{ margin-top: 30px; } #Message{ font: 14px "Microsoft Yahei"; padding: 5px; color: #666; resize: none; height: 148px; 300px; border-radius: 5px; background-color: #faf8f9; } .betn_megSubmit{ display: block; 180px; height: 40px; border: 1px solid #fa6104; background: #fa6104; color: #fff; border-radius: 5px; line-height: 30px; float: left; font-size: 18px; margin-left: 139px; _margin-left: 37px; margin-right: 30px; cursor: pointer; margin-top: 15px; } </style> </head> <body> <div class="out-border"> <div class="meg1"> <span class="sp1">留言板</span> </div> <form action="/hello/" method="post"> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 用户名 </span > <input type="text" name="user" class="user_meta"> </div> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 密码 </span> <input type="password" name="pwd" class="user_meta"> </div > <div class="itemc"> <span class="left_content"> <b class="star">*</b> 邮箱 </span> <input type="email" name="email" class="user_meta"> </div> <div class="itemc"> <span class="left_content"> <b class="star">*</b> 留言 </span> <!-- textarea两个标签不要有空格,不然光标不会放到第一个位置--> <textarea name="message" id="Message" cols="30" rows="10"></textarea> </div> <input type="submit" class="betn_megSubmit" value="提交留言"> <!-- {% csrf_token %} --> </form> </div> </body> </html>
MariaDB [mytest]> create table msgtb(name varchar(20), pwd varchar(20), email varchar(50), msg varchar(100)); Query OK, 0 rows affected (0.03 sec) MariaDB [mytest]> desc msgtb; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | pwd | varchar(20) | YES | | NULL | | | email | varchar(50) | YES | | NULL | | | msg | varchar(100) | YES | | NULL | | +-------+--------------+------+-----+---------+-------+ 4 rows in set (0.01 sec) MariaDB [mytest]>
下面要做的就是把通过前端页面填写的信息,保存到数据库中。
因为要使用python的第三方orm映射,因此首先在django的工程目录下面,创建如下py文件!
这个文件主要作用是对MySQLdb进行封装,以方便调用接口直接查询,插入数据。
# *-* coding:utf-8 *-* # Auth: wangxz import MySQLdb class DbConn(object): def __init__(self, host, user, port, pwd, dbname): self.__host = host self.__user = user self.__port = port self.__pwd = pwd self.__dbname = dbname self.__db_obj = MySQLdb.connect( host=self.__host, user=self.__user, port=self.__port, passwd=self.__pwd, db=self.__dbname ) # 调用的时候,传递的参数是查询语句,返回的第一条数据 def query(self, querys, str1): cursor = self.__db_obj.cursor() cursor.execute(querys, str1) result = cursor.fetchone() return result # 返回所有的数据 def query_all(self, querys): cursor = self.__db_obj.cursor() cursor.execute(querys) result = cursor.fetchall() return result # 调用的时候,传递的参数是插入语句 def insert_data(self, data, args): cursor = self.__db_obj.cursor() cursor.execute(data, args) self.__db_obj.commit() if __name__ == "__main__": DB_msg = { "host": "10.0.102.204", "user": "root", "port": 3306, "pwd": "123456", "dbname": "mytest", } db1 = DbConn(**DB_msg) sqls = "select * from mytest where name=%s and pwd=%s" str1 = ["wxz", "123"] data = db1.query(sqls, str1) print(data)
视图文件views.py如下:
# *-* coding:utf-8 *-* from django.shortcuts import HttpResponse from django.shortcuts import render # Create your views here. from DBAction import DbConn DB_msg = { "host": "10.0.102.204", "user": "root", "port": 3306, "pwd": "123456", "dbname": "mytest", } db_obj = DbConn(**DB_msg) def main(request): if request.method == "GET": return render(request, "main.html") elif request.method == "POST": username = request.POST.get("user") pwd = request.POST.get("pwd") email = request.POST.get("email") msg = request.POST.get("message") insert_msg = (username, pwd, email, msg) insert_sql = "insert into msgtb(name, pwd, email, msg) values(%s, %s, %s, %s)" db_obj.insert_data(insert_sql, insert_msg) select_sql = "select * from msgtb" select_data = db_obj.query_all(select_sql) print "The query result is:", select_data return HttpResponse("What a fuck!")
#需要说明的是这个文件没有后端展示功能,借助了查询接口,直接把数据库中的数据打印了出来。
在urls中加入对应的映射:
from mysite.views import main urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^main/', main), ]
运行这个文件,在前端填写数据,提交信息,会跳转到“what a fuck”的页面。并且在pycharm中会有如下输出:
[21/Jan/2019 19:23:32] "GET /main/ HTTP/1.1" 200 1745
#查询出来的结果 The query result is: (('wangxz', '1234qwer', '234234@qq.com', 'God is a girl!'), ('wangxz', '1234qwer', '10549@qq.com', 'what a fuck!!'), ('wangxz', ' 1234qwer', '10549@qq.com', 'what a fuck!!')) [21/Jan/2019 19:23:37] "POST /main/ HTTP/1.1" 200 12
以上一个简单的实例,来说明了model层的作用。上面的实例可以知道,如果使用python第三方的orm,需要自己写sql语句,自己对字段的条件进行约束,这些对开发来说都是额外的工作,因此django提供了model模块,来完成的这些操作,开发者不需要关注sql语句的实现,只需要关注逻辑层的应用即可!
来总结一下,创建一个简单django工程的步骤:
- 首先创建django工程文件,可以使用pycharm工具直接创建。
- 创建对应的app应用,注意app名称需要在settings.py中注册。python manage.py startapp appname
- 如果使用pycharm创建那么templates文件就会直接写到settings.py中,否则需要手动加入。
- 如果使用css和js文件,需要创建static目录,目录仍然需要在settings.py中注册。
- 写url映射,写视图文件,视图文件需要调用前端代码,前端代码存在templates目录中,前端代码的格式文件存在static目录中。
- 视图文件中还涉及与后端的交互操作,而后端数据库的定义需要在models.py中指定
- 若是使用了django自带的orm(推荐使用自带的orm),还需要使用python manage.py makemigrations, python manage.py migrate来生成对应的数据库及表。
一些注册操作:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "mysite", #自己创建的app写在这里,注意格式 ]
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], ........ #找到对应的templatees写入第二行,
STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )
目前整个django工程的目录结构如下: