Django 之 流程和命令行工具

一、一个简单的web框架

框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。

对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

1 1 import socket 2 2 3 3 def handle_request(client): 4 4 5 5 buf = client.recv(1024) 6 6 client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) 7 7 client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) 8 8 9 9 def main(): 1010 1111 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1212 sock.bind(('localhost',8001)) 1313 sock.listen(5) 1414 1515 while True: 1616 connection, address = sock.accept() 1717 handle_request(connection) 1818 connection.close() 1919 2020 if __name__ == '__main__': 2121 2222 main()

View Code

      最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

      正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

在python中提供一个接口,帮我们封装socket,即wsgiref模块:Web Server Gateway Interface。

1 1 from wsgiref.simple_server import make_server 2 2 3 3 4 4 def RunServer(environ, start_response): 5 5 start_response('200 OK', [('Content-Type', 'text/html')]) 6 6 return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]#返回的内容 7 7 8 8 9 9 if __name__ == '__main__': 1010 httpd = make_server('', 8000, RunServer) 1111 print("Serving HTTP on port 8000...") 1212 httpd.serve_forever()

1整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写, 2我们只负责在更高层次上考虑如何响应请求就可以了。 3 4application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。 5 6Python内置了一个WSGI服务器,这个模块叫wsgiref 7 8 9application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数: 10 11 //environ:一个包含所有HTTP请求信息的dict对象; 12 13 //start_response:一个发送HTTP响应的函数。 14 15在application()函数中,调用: 16 17start_response('200 OK', [('Content-Type', 'text/html')]) 18 19就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。 20start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每 21个Header用一个包含两个str的tuple表示。 22 23通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。 24 25然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。 26 27有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML28通过start_response()发送Header,最后返回Body。

注意:

只要有请求,就会触发RunServer函数,

1environ封装了客户端发来的所有数据, 2 3start_response封装要返回给用户的数据,比如:响应头,状态等

现在我们访问localhost:8000,显示出来的都是hello,web,一般的网站的url都会有什么/data,/index等,用来显示不同的页面内容,那我们应该怎么做呢?

我们设置断点,进入调试模式,在运行浏览器可以看到:

environ中有很多的参数,我们找到一个叫做PATH_INFO的参数,那个就是显示我们url后面有什么。

这样我们就能够通过url进行判断,然后进入相应的页面:

1from wsgiref.simple_server import make_server 2 3def handle_index(): 4 return [bytes('<h1>Hello, Index!</h1>', encoding='utf-8'), ] 5def hanle_date(): 6 return [bytes('<h1>Hello, Date!</h1>', encoding='utf-8'), ] 7 8def RunServer(environ, start_response): 9 start_response('200 OK', [('Content-Type', 'text/html')]) 10 currnet_url = environ['PATH_INFO']; 11 if currnet_url =='/index': 12 return handle_index() 13 elif currnet_url =='/date': 14 return hanle_date() 15 else: 16 return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ] 17 18 19if __name__ == '__main__': 20 httpd = make_server('', 8000, RunServer) 21 print("Serving HTTP on port 8000...") 22 httpd.serve_forever()

 

通过这个我们完成了一些基本的操作。

那如果说url很多,我们不可能一个一个去判断吧,那我们应该怎么做呢?python中几乎所以的web框架都是把所有的url放在一个列表中: 然后一类的url可以通过正则表达式进行匹配

1URL_DICT = { 2 "/index":handle_index, 3 "/date":handle_date, 4} 5def RunServer(environ, start_response): 6 start_response('200 OK', [('Content-Type', 'text/html')]) 7 currnet_url = environ['PATH_INFO']; 8 func = None 9 if currnet_url in URL_DICT: 10 func = URL_DICT[currnet_url] 11 if func: 12 return func() 13 else: 14 return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ]

 我们看上面的代码,如果我们把return里的html放在一个html文件中,并放在View文件夹中;把handle_index等处理业务逻辑的函数写在一个py文件中并放在Controller文件夹中。从数据库读取的方法放在Model文件夹中。

我们需要html的时候就打开html文件f=open("html文件",mode="rb")然后read读取就可以了。

我们需要用函数的时候就直接from Controller import 文件名,然后用文件名.函数名就可以了。

我们在html中想要用一些特殊的符号,数据从数据库中获取替换,也只要引入model文件家中的方法,读出数据之后用replace函数替换符号和函数就可以了。

MVC:

Model数据库    View模板文件    Controller业务处理

MTV:(Django是基于MTV的框架)

Model数据库    Template模板文件    View业务处理

二、Django

2.1、安装Django

安装:pip install django;

安装完之后就多了一个可执行文件

2.2、创建django程序

方式一:通过命令行进入你要创建的目录下,然后输入命令 :django-admin.exe startproject mydjango

      

  方式二:通过pycharm直接创建Django程序

  

2.2.1、工程目录

1├── mysite 2 └── mysite #这个才是工程的包名。 3 ├── __init__.py #表明mysite是一个包。 4 ├── settings.py #Django的配置文件,包括工程的app配置、数据库配置、语言配置等。 5 ├── urls.py   #Django的调度者,根据不同的url映射到不同的视图。 6 └── wsgi.py #WSGI是web server gateway interface,这个文件是使project符合这种协议的入口点(entry-point 指令变换点) 7 ├── manage.py #与Django进行交互的命令行工具,比如后面根据model生成数据库表结构、供开发使用的server等都是使用该工具,在manage.py的同级目录使用python manage.py 可以看到可以使用的命令列表

2.3运行Django程序

**方式一:**进入程序目录下通过命令行运行

python manage.py runserver (127.0.0.1:8001),默认端口号为8000

方式二:在pycharm中运行

要注意要运行你的项目名称,而不是manage.py或者是其他的文件

如果要改运行的url和端口名:直接在host和port中设置就可以了

2.4、创建app

一个project可以又多个app,一个app可以同时属于多个project。通过以下命令创建一个app(在project目录下)

创建app:  python manage.py startapp cmdb

2.4.1、app目录

1. 2├── manage.py 3├── django_learn 4│ ├── __init__.py 5│ ├── settings.py 6│ ├── urls.py 7│ └── wsgi.py 8└── cmdb # app的根目录 9 ├── admin.py #Django自带了一个管理界面,这个文件可以注册model在界面中管理 10 ├── apps.py #配置当前app 11 ├── __init__.py #表明polls也是一个包 12 ├── migrations #用来初始化数据库,在执行python manage.py makemigrations 的时候会自动生成一个文件在这里 13 │ └── __init__.py #表明migrations也是一个包 14 ├── models.py #写指定的类,通过命令可以创建数据库结构 15 ├── tests.py #写测试代码 16 └── views.py  #业务代码 Django映射urls.py里面的url的时候,在views.py里面查找对应的处理方法

三、练习--提交数据并展示(数据库)

需求:

1.首先在django_learn文件夹下面创建templates文件夹用于存放html文件。

如果在执行程序的时候,报找不到template的错误,那么是settings里面定义的路径的问题。

2.在配置文件urls.py中指定路由关系:

 3.在cmdb这个app的view下定义用户的处理逻辑: 

这里django中有render模块直接封装了文件的打开读取关闭的过程。传入的index.html的路径名是由django_learn下面的setting中的templates决定的(位置见1中ps):

4.导入静态文件

在mysite下面建立文件夹statics

在templates下的html文件里面添加引用

<script src="/static/jquery-1.12.4.js"></script> 

  在settings.py里面定义静态文件的路径

1STATIC_URL = '/static/' #作用:如果下面的tatics名字变了,仍然可以用static来进行静态文件的路径拼接, 2 # 此时<script src="https://my.oschina.net/statics/jquery-1.12.4.js"></script> = <script src="https://my.oschina.net/static/jquery-1.12.4.js"></script> 3 #目的是防止路径变化导致前端人员引入静态文件的路径都得改,所以前端人员统一用/static进行拼接就行了 4STATICFILES_DIRS = ( 5 os.path.join(BASE_DIR,'statics'), 6)

  注意这里静态文件的URL要与src引入的路径相匹配,然后通过http://127.0.0.1:8000/statics/jquery-1.12.4.js访问JQuery成功。

5.我们现在没有做数据处理,我们点击提交:出现了CSRF的错误

如果我们不想要这个错误的话可以把settings中的代码注释了:

再次输入127.0.0.1:8080/userInfo 就可以访问啦!!

6.上面表单的提交在页面刷新以后就没有了,因为内容是存放在缓存中的,现在,我们需要将数据存放在数据库当中,改写之前的代码。

  在models.py中创建userInfo的类:

1class userinfo(models.Model): 2 username=models.CharField(max_length=64) 3 sex = models.CharField(max_length=64) 4 email= models.CharField(max_length=64)

  在settings.py中注册cmdb,并且查看DATABASES的设置:

1INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 'cmdb', #必须先注册,否则下面会报错 9]

  执行命令创建数据库,表

1D:\Python\mysite>python manage.py makemigrations 2Migrations for 'cmdb': 3 cmdb\migrations\0001_initial.py: 4 - Create model UserInfo 5 6D:\Python\mysite>python manage.py migrate 7Operations to perform: 8 Apply all migrations: admin, auth, cmdb, contenttypes, sessions 9Running migrations: 10 Applying contenttypes.0001_initial... OK 11 Applying auth.0001_initial... OK 12 Applying admin.0001_initial... OK 13 Applying admin.0002_logentry_remove_auto_add... OK 14 Applying contenttypes.0002_remove_content_type_name... OK 15 Applying auth.0002_alter_permission_name_max_length... OK 16 Applying auth.0003_alter_user_email_max_length... OK 17 Applying auth.0004_alter_user_username_opts... OK 18 Applying auth.0005_alter_user_last_login_null... OK 19 Applying auth.0006_require_contenttypes_0002... OK 20 Applying auth.0007_alter_validators_add_error_messages... OK 21 Applying auth.0008_alter_user_username_max_length... OK 22 Applying cmdb.0001_initial... OK 23 Applying sessions.0001_initial... OK

  在用户逻辑views.py中需要引入models操作数据库

1from cmdb import models 2def userInfo(request): 3 if request.method=="POST": 4 u=request.POST.get("username",None) 5 s=request.POST.get("sex",None) 6 e=request.POST.get("email",None) 7 # ---------表中插入数据方式一 8 # info={"username":u,"sex":e,"email":e} 9 # models.UserInfor.objects.create(**info) 10 11 # ---------表中插入数据方式二 12 models.userinfo.objects.create( 13 username=u, 14 sex=s, 15 email=e 16 ) 17 userlist=models.userinfo.objects.all() 18 # for i in userlist: 19 # print(i.username,i.sex,i.email) 20 return render(request,"index.html",{"userlist":userlist})

  在显示页面上index.html显示数据库中提取的数据:

1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6</head> 7<body> 8<form action="/userInfo" method="post"> 9 <p>姓名<input type="text" name="username"></p> 10 <p>性别<input type="text" name="sex"></p> 11 <p>邮箱<input type="text" name="email"></p> 12 <p><input type="submit" value="submit"></p> 13</form> 14 15<h1>数据展示</h1> 16<table border=1px> 17 <tr> 18 <td>姓名</td> 19 <td>性别</td> 20 <td>年龄</td> 21 </tr> 22 <tr> 23 {% for i in userlist %} 24 <td>{{i.username}}</td> 25 <td>{{ i.sex }}</td> 26 <td>{{ i.email }}</td> 27 28 </tr> 29 {% endfor %} 30</table> 31</body> 32</html>

 #返回数据:HttpResponse("str")       return render(request,"html文件路径","html中要替换的变量":USER_LIST)            return redirect("/只能填URL路径")     

7.模板渲染

 模板语言:

1--{{变量名}} 2    def func(request): 3      return render(request,'index.html',{'current_user':"alex"}) 4    index.html中 5    <html> 6    ........ 7      <body> 8        <div>{{current_user}}</div>#这样用alex替换了current_user 9      </body> 10    </html> 11  --For循环 12 userlist=[] 13 def userInfo(request): 14 if request.method=="POST": 15 username=request.POST.get("username",None) 16 sex=request.POST.get("sex",None) 17 email=request.POST.get("email",None) 18 user={"username":username,"sex":sex,"email":email} 19 userlist.append(user) 20 return render(request,"index.html",{"userlist":userlist}) 21    index.html中 22    <html> 23    ........ 24      <body> 25 <table border=1px> 26 <tr> 27 <td>姓名</td> 28 <td>性别</td> 29 <td>邮箱</td> 30 </tr> 31 <tr> 32 {% for i in userlist %} 33 <td>{{i.username}}</td> 34 <td>{{ i.sex }}</td> 35 <td>{{ i.email }}</td> 36 </tr> 37 {% endfor %} 38 </table> 39      </body> 40    </html> 41  --索引 42    def func(request): 43      return render(request,'index.html',{ 44               'current_user':"alex", 45               'user_list':['xiaoming','liangliang'] 46               'user_dict':{'k1':'v1','k2':'v2'}}) 47    index.html中 48    <html> 49    ........ 50      <body> 51        <a>{user_list.0/1}</a> 52 53      </body> 54    </html> 55  --条件 56    {%if age %} 57      <a>有年龄</a> 58    {% else %} 59      <a>无年龄</a> 60    {% endif %} 61  --循环字典 62    {%for k,row in dict.items%}#同时获得key和value 63      <li>{{k}}-{{row}}</li> 64    {%endfor%} 65    {%for row in dict.keys%}#获得字典中的key 66      <li>{{row}}</li> 67    {%endfor%} 68    {%for row in dict.values%}#获得字典中的value 69      <li>{{row}}</li> 70    {%endfor%}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Django 之 流程和命令行工具 - HelloWorld