说明:我是先上手做一些简单的例子,然后在尝试的过程中理解Django的原理,笔记也是按这个思路来的。
一、Django结构与基本文件介绍
1. django-admin.py
工程管理工具,主要用于创建项目和app等。
例:django-admin.py startproject project_example
会创建一个名为project_example的工程,目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- manage.py
2. manage.py
命令行工具,用于和Django项目进行交互。
比如:
python manage.py startapp app_example //创建名为app_example的app
python manage.py runserver 0.0.0.0:8000 //启动app服务,0.0.0.0是让其他电脑可以连接到服务器,8000是端口,默认就是8000
python manage.py syncdb //连接数据库创建表
3. settings.py
Django工程的配置文件,主要有以下几个:
(1)
INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app_example‘, ]
在这里添加我们自己创建的app的目录名,不添加在这里就无法调用app中的内容。
(2)
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘test‘, ‘USER‘: ‘test‘, ‘PASSWORD‘: ‘test123‘, ‘HOST‘:‘localhost‘, ‘PORT‘:‘3306‘, }
设置连接数据库的信息
(3)
TEMPLATES = [ { ‘BACKEND‘: ‘django.template.backends.django.DjangoTemplates‘, ‘DIRS‘: [], ‘APP_DIRS‘: True, ‘OPTIONS‘: { ‘context_processors‘: [ ‘django.template.context_processors.debug‘, ‘django.template.context_processors.request‘, ‘django.contrib.auth.context_processors.auth‘, ‘django.contrib.messages.context_processors.messages‘, ], }, }, ]
模板信息,‘DIRS‘是模板所在路径,比如在最外层的project_example目录下建一个模板文件夹templates。则应这样写: ‘DIRS‘: [BASE_DIR+"/templates",],
目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- manage.py
| |-- templates
| |-- user_info.html
(4)
LANGUAGE_CODE = ‘en-us‘ //语言 TIME_ZONE = ‘UTC‘ //时间
4. urls.py
该Django项目的URL声明,一份由Django驱动的网站"目录"。
一般格式:
from project_example.view import hello urlpatterns = patterns("", (‘^hello/$‘, hello), )
(1) 先导入view对象或者相应的视图函数。
(2) 然后指定URL与相应函数的对应关系
(3) 当客户端访问某个URL时就会调用相应函数
例如:
from project_example import view urlpatterns = patterns("", (‘^test1/$‘, view.test1), (‘^test2/$‘, view.test2), )
当访问 localhost:8000/test1 时就会调用view.test1()函数,访问 localhost:8000/test2 时就会调用view.test2()函数.
5. 用不到的文件
__init__.py:空文件,告诉Python该目录是一个Python包。
wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目
二、一个简单Django例子的运行流程
1. 创建模板文件,也就是上述的templates/user_info.html
例:
<html> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>用户信息</title> <head></head> <body> <h3>用户信息:</h3> <p>姓名:{{name}}</p> <p>年龄:{{age}}</p> </body> </html>
在模板里,我们只填共用组件,至于那些因‘人’而异的组件就用Django的特殊标签来代替。
比如这里name和age是因‘人’而异的,所以我们用{{name}}{{age}}这两个变量表示,具体的值由view.py中的视图函数去填充。
2. 创建视图函数
首先在内存的project_example中创建view.py文件,然后在其中添加对象,用于向模板提交数据。
目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- view.py
| |-- manage.py
| |-- templates
| |-- user_info.html
view.py内容:
这里我试了这两种写法都可以
from django.shortcuts import render from django.shortcuts import render_to_response def user1(request): name = ‘aaa‘ age = 24 return render_to_response(‘user_info.html‘,locals()) def user2(request): name = ‘bbb‘ age = 18 context = {} context[‘name‘] = ‘bbb‘ context[‘age‘] = ‘18‘ return render(request, ‘user_info.html‘, context)
3. 修改urls.py
from django.conf.urls import url from project_example import view urlpatterns = [ url(r‘user1/$‘, view.user1), url(r‘user2/$‘, view.user2), ]
4. 发布服务
python manage.py runserver 0.0.0.0:8000
5.登录网址
http://localhost:8000/user1/
显示如下:
用户信息:
姓名:aaa
年龄:24
http://localhost:8000/user2/
显示如下:
用户信息:
姓名:bbb
年龄:18
三、 view.py文件中的视图函数语法解析(待填充)
例一:
def user2(request): name = ‘bbb‘ age = 18 context = {} context[‘name‘] = ‘bbb‘ context[‘age‘] = ‘18‘ return render(request, ‘user_info.html‘, context)
例二:
def user1(request): name = ‘aaa‘ age = 24 return render_to_response(‘user_info.html‘,locals())
四、Http通信
这里先只讲一下POST通信
1. 创建html模板进行通信
代码:
<html> <head> <meta charset="utf-8" /> <title>Search - w3cschool.cc</title> </head> <body> <form action="/search-post/" method="post"> {% csrf_token %} <input type="text" name="q"> <input type="submit" value="Submit"> </form> <p>{{ rlt }}</p> </body> </html>
2. 内层 project_example 目录下创建search.py
目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- view.py
| |-- search.py
| |-- manage.py
| |-- templates
| |-- user_info.html
search.py代码:
from django.shortcuts import render #from django.core.context_processors import csrf 1.2版本之前 #from django.contrib.auth.context_processors import csrf 1.2~1.4版本 from django.template.context_processors import csrf #1.10版本 # 接收POST请求数据 def search_post(request): ctx ={} ctx.update(csrf(request)) if request.POST: ctx[‘rlt‘] = request.POST[‘q‘] else: ctx[‘rlt‘] = ‘here‘ return render(request, "post.html", ctx)
3.添加urls.py
from django.conf.urls import url from project_example import view from project_example import search urlpatterns = [ url(r‘user1/$‘, view.user1), url(r‘user2/$‘, view.user2), url(r‘search-post/$‘, search.search_post), ]
4.发布+访问
python manage.py runserver 0.0.0.0:8000
http://localhost:8000/search-post/
5.请求流程
用户发送请求 -> 服务端执行search_post(),if不成立 -> 显示post.html页面 -> 在该页面点击提交按钮之后数据再次传递给localhost:8000/search-post/ -> 服务端再次执行search_post(),这次if成立
五、JSON解析
Python中有专门编码和解码JSON的模块Demjson,他提供了两个方法
demjson.encode():将 Python 对象编码成 JSON 字符串 demjson.decode():将已编码的 JSON 字符串解码为 Python 对象
例:
import demjson data = [ { ‘a‘ : 1, ‘b‘ : 2, ‘c‘ : 3, ‘d‘ : 4, ‘e‘ : 5 } ] json = demjson.encode(data) print json
结果:[{"a":1,"b":2,"c":3,"d":4,"e":5}] //json字符串
json = ‘{"a":1,"b":2,"c":3,"d":4,"e":5}‘; text = demjson.decode(json) print text
结果:{u‘a‘: 1, u‘c‘: 3, u‘b‘: 2, u‘e‘: 5, u‘d‘: 4} //字典对象
六、数据库操作
1. 设置setting.py文件中的数据库配置
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘test‘, ‘USER‘: ‘test‘, ‘PASSWORD‘: ‘test123‘, ‘HOST‘:‘localhost‘, ‘PORT‘:‘3306‘, }
这里面的用户信息要和电脑上MySQL中的用户信息相同。
2. Django规定使用模板必须创建APP对象
命令: python manage.py startapp TestModel
目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- view.py
| |-- search.py
| |-- manage.py
| |-- templates
| |-- user_info.html
| |-- TestModel
| |-- __init__.py
| |-- admin.py
| |-- models.py
| |-- tests.py
3. 修改TestModel/models.py文件,Django会根据这个文件创建表
代码:
from django.db import models class Test(models.Model): name = models.CharField(max_length=20) age = models.IntegerField(max_length=3)
这里指定了一个名为 TestModel_Test 的表。(表名:目录名_类名)
表中有3个字段:id(默认),name,age
4. 在内层的project_example目录下创建testdb.py保存执行数据库操作函数
目录结构如下:
|-- project_example
| |--project_example
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |-- view.py
| |-- testdb.py
| |-- manage.py
| |-- templates
| |-- user_info.html
| |-- TestModel
| |-- __init__.py
| |-- admin.py
| |-- models.py
| |-- tests.py
testdb.py代码:
from django.http import HttpResponse from TestModel.models import Test # 数据库操作 def testdb(request): #添加数据 test1 = Test(name=‘w3cschool.cc‘) test1.save() # 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM list = Test.objects.all() # filter相当于SQL中的WHERE,可设置条件过滤结果 response0 = Test.objects.filter(id=1) # 获取单个对象 response1 = Test.objects.get(id=1) return HttpResponse("<p>数据库操作成功!</p>")
5.修改urls.py文件并发布
from django.conf.urls import url from project_example import view from project_example import search from project_example import testdb urlpatterns = [ url(r‘user1/$‘, view.user1), url(r‘user2/$‘, view.user2), url(r‘search-post/$‘, search.search_post), url(r‘testdb/$‘, testdb.testdb), ]
发布:python manage.py runserver 0.0.0.0:8000
七、尝试了一些简单例子之后,回顾理解Django结构
Django主要分为三部分:模板、模型、表单
模板:表现逻辑部分,就是上述的view.py文件,主要负责Web开发中展现的页面内容。在App开发中应该就是逻辑运算部分,名字就不用view了。
模型:数据存取逻辑,也就是数据库操作那部分。
表单:业务逻辑,对应着urls.py文件,根据用户传来的数据决定调用模板中的哪些函数来处理。
八、关于APP开发的一些构想
1. 客户端根据请求的类型访问不同的URL
比如:
http://192.168.1.101:8000/1/
http://192.168.1.101:8000/2/
http://192.168.1.101:8000/3/
...
然后通过POST传递给客户端JSON数据
2. 服务端在urls.py中根据URL调用不同的函数,读取POST数据,处理完之后返回一个JSON。
疑问:
1.如何在JS写的客户端发送数据?
拿上面那个HTPP通信中post的例子尝试一下数据传输,我使用GET没问题,因为我没有传数据,只是获取数据,可是用POST就一直报403,应该是传的数据格式内容有问题。
现在的服务端视图函数如下:
from django.shortcuts import render from django.template.context_processors import csrf # 接收POST请求数据 def search_post(request): ctx ={} ctx.update(csrf(request)) if request.POST: ctx[‘rlt‘] = request.POST[‘q‘] else: ctx[‘rlt‘] = ‘get‘ return render(request, "post.html", ctx)
post.html:通过这个html网址是能够正确传输数据的
<html> <head> <meta charset="utf-8" /> <title>Search - w3cschool.cc</title> </head> <body> <form action="/search-post/" method="post"> {% csrf_token %} <input type="text" name="q"> <input type="submit" value="Submit"> </form> <p>{{ rlt }}</p> </body> </html>
//JS程序中,通过这段代码就不能正确传输数据了
var oAjax=new ActiveXObject("Microsoft.XMLHTTP"); oAjax.open("POST", http://localhost:8000/search-post/, true); oAjax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); oAjax.send("q=hello");
//当然,通过GET能够正常读取返回数据
var oAjax=new ActiveXObject("Microsoft.XMLHTTP"); oAjax.open("GET", http://localhost:8000/search-post/, true); oAjax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); oAjax.send();
我想,问题应该是POST传输的数据不对,传输的数据应该不仅仅是 "q=hello" 。那这里send()里面的格式应该是什么样的呢?或者说我在服务端要怎样设置才能接收这样的数据?
2. 进一步扩展,我要是想在客户端传递一个JSON数据,客户端应该怎样设置参数,服务端又应该怎样设置参数呢?