1、Python的使用
动态加载类
#定义需要导入的类已经执行的方法,存放于数组中
subpro=["wxroot.wxserver.subpro_savemsg,SaveMsg,saveRecMsg","wxroot.wxserver.subpro_savemsg,SaveMsg,saveSendMsg"]
m=import_module(subpro[0].split(",")[0])#根据模块的路径导入模块
c=getattr(m, subpro[0].split(",")[1])()#获取SaveMsg类的实例
me=getattr(c, subpro[0].split(",")[2])#执行SaveMsg类中saveRecMsg方法
获取文件路径
1、获取当前执行的脚本所在的绝对路径和文件名,脚本如下:
import unittest
import os
class Test(unittest.TestCase):
def testGetPath(self):
filepath=__file__
filename=filepath.split('/')[-1]
dirname1 = os.path.dirname(__file__)
realpath1= os.path.realpath(__file__)
abspath1=os.path.abspath(filename)
dirname2 = os.path.dirname(filename)
realpath2= os.path.realpath(filename)
print(vars())
if __name__ == "__main__":
import sys;sys.argv = ['', 'Test.testGetPath']
unittest.main()
输出如下:
{'dirname1': '/home/yy/weixin/leyaworld/1/wxtest/tokentest', 'realpath1': '/home/yy/weixin/leyaworld/1/wxtest/tokentest/testmain.py', 'self': <__main__.Test testMethod=testGetPath>, 'filename': 'testmain.py', 'dirname2': '', 'realpath2': '/home/yy/weixin/leyaworld/1/wxtest/tokentest/testmain.py', 'filepath': '/home/yy/weixin/leyaworld/1/wxtest/tokentest/testmain.py', 'abspath1': '/home/yy/weixin/leyaworld/1/wxtest/tokentest/testmain.py'}
可知:
__file__就是文件绝对路径,
dirname(__file__)得到不包含文件名的绝对目录
dirname(filename)得到文件的相对路径
realpath(__file__)得到文件的绝对路径
realpath(filename)得到文件的绝对路径
abspath(filename)得到文件的绝对路径
2、获取django工程绝对路径
由于django项目中setting.py文件的保存位置就是在根目录下面,所以可以在setting中加入如下语句来获取Django项目的跟路径
Path = os.path.dirname(__file__)
3、相对路径的使用
使用dirname(filename)获取文件的相对路径
相对路径在编程中没什么实际作用,经常使用的是dirname函数的场景是获取上一层目录
例如dirname(abspath(filename))就是获取文件所在的目录
dirname(dirname(abspath(filename)))获取的就是文件所在目录的上一层目录
python的内建变量
1、__name__:
__name__指示模块应该如何被加载,如果是被导入,__name__的值为模块名字,如果是直接执行,__name__的值为'__main__',如下:
测试类如下:
from wxtest.tokentest.testsub1 import TestClass1
import unittest
class Test(unittest.TestCase):
def testName(self):
tc=TestClass1()
print(tc.prinInfo())
if __name__ == "__main__":
sys.argv = ['', 'Test.testName']
unittest.main()
testsub1.py文件如下:
class TestClass1(object):
def __init__(self):
def prinInfo(self):
print("TestClass1=",__name__)
执行结果如下:
testGetName= __main__
TestClass1= wxtest.tokentest.testsub1
2、__file__:
代表当前文件路径,os.path.dirname(__file__)获取的不带文件名的路径,如下:
/home/yy/weixin/leyaworld/1/wxtest/tokentest/
直接__file__获取的是带文件名的路径,如下:
/home/yy/weixin/leyaworld/1/wxtest/tokentest/testmain.py
3、__doc__:输出当前模块的Doc内容如下:
def testGetDoc(self):
print("testGetName=",__doc__)
输出:
doc=
Created on Feb 17, 2017
@author: yy
其中上面的注释实在创建模块是自动生成的
Django工程配置--适配SAE
Django static 文件在SAE上不加载问题
【问题描述】
在本地创建的工程可以正常解析访问HTML,能够成功加载css和js文件,但是文件上传到SAE上就不能加载CSS和Js,通过在浏览器上查看html页面的source代码,css和js文件的链接代码如下:
<link rel="stylesheet" href="/static/wxroot/css/wx.css">对应的访问的URL如下:
http://XXX.applinzi.com/static/wxroot/css/wx.css,浏览器打开此地址提示404 Not Found错误
【环境信息】
工程目录:
mysite
|--mysite
setting.py
urls.py
|--static
|--wxroot
|--static
|--wxroot
|--css
wx.css
|--js
wx.js
setting.py关键配置如下:
DEBUG = True
STATIC_ROOT=os.path.join(BASE_DIR, "static")
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "wxroot/static"),
)
urls.py配置如下:
urlpatterns = [
url(r'^$', include('wxroot.urls',namespace="root")),#
url(r'^admin/', include(admin.site.urls)),
url(r'^wxroot/', include('wxroot.urls',namespace="wxroot")),
【原因分析】
1、背景:Django本身就对静态文件解析支持不是很好,它侧重的是业务的逻辑,像js和css这样的页面静态加载的文件,Django项目推荐使用其他应用服务器,例如apache进行部署,然后再远程网络加载,所以在Django正式部署的project中静态文件加载的功能是默认关闭的,此功能在开发模式(即debug)才会开启。工程的debug模式在setting.py文件设置,DEBUG=True表示开发模式,False表示发布模式
2、原因:在本地开发使用的Django工程,使用了开发模式(Debug),但是SAE对静态文件的路径有自己默认处理,将工程跟路径下的static文件作为static文件存放的位置,但是本地的工程将static文件放在app的子路径下,SAE找不到,结果就是在本地调试好好的HTML页面,上传到SAE上就不行了
【解决方法】
sae官网给了配置静态文件的方法,地址http://www.sinacloud.com/doc/sae/python/tutorial.html#serve-admin-app
方法一:(使用于Debug和非Debug模式)
修改 settings.py 中的 STATIC_ROOT 为应用目录下 static 子目录的绝对路径。//此步骤已经配置,STATIC_ROOT=os.path.join(BASE_DIR, "static")即工程根目录的static文件夹
运行 python manage.py collectstatic 将静态文件收集到应用的 static 子目录下。//目的是将wxroot 子路径下的static文件内容复制到根目录的static,需要在setting中配置STATICFILES_DIRS,其中包含wxroot的static文件绝对路径,collectstatic会根据这个配置进行复制,也可以手工进行复制不通过命令
修改 config.yaml ,添加对 static 文件夹下的静态文件的 handlers。//实际测试,不需要执行此步骤,已经可以加载静态文件
handlers:
- url: /static
static_dir: path/to/mysite/static
总结,此方法适用于Debug为True和False的情况,不足的地方是每次修改wxroot下的静态文件后,都要执行python manage.py collectstatic将根目录下发static文件内容页更新,不过静态文件变动的比较少,此法还是比较好的
方法二:(只适用部署模式为Debug模式)
在开发调试(settings.py 中 DEBUG=True)过程中,可以将 staticfiles_urlpatterns 加到你的 URLConf,让 Django 来处理 admin app 的静态文件:
# urls.py
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
#...
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
#只追加如下两句即可
from django.contrib.staticfiles.urls import staticfiles_urlpatternsurlpatterns += staticfiles_urlpatterns()
由于新浪云默认 static 为静态文件目录,需要修改 config.yaml,添加任意一条规则覆盖默认行为。//下面两句直接复制粘贴即可,本身没有作用,只是让默认的规则不起作用
# config.yaml
handlers:
- url: /foo
static_dir: foo
总结:此方法只能在debug模式下生效,好处是只用部署和维护一个static文件
其他相关的解决方法参考:https://my.oschina.net/zyzzy/blog/173262
还有一种解决方法,可以实现在非Debug模式下,APP子路径下的静态文件也不用复制到跟路径。
原理很简单,通过配置urls.py,加载css文件时提示404 Not Found的错误消除,使其找到对应的静态文件
css文件的访问网址是http://127.0.0.1:8000/static/wxroot/css/wx.css,默认在根路径的static中查找css文件,找不到报错,现在配置urls.py,追加如下语句:
from django.conf.urls import patterns
urlpatterns += patterns('',
url(r'^static/admin/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.STATIC_ROOT_ADMIN,}),
url(r'^static/wxroot/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.STATIC_ROOT_WXROOT,}),
)
第一个url匹配的访问地址是static/admin/XXXX,STATIC_ROOT_ADMIN为在setting.py中添加的变量,值为admin的static文件根路径如下:/opt/mysite/static/admin/
第二个url匹配的访问地址是static/wxroot/XXXX,STATIC_ROOT_WXROOT为在setting.py中添加的变量,值为wxroot的static文件根路径如下:/opt/mysite/wxroot/static/wxroot/
XXXX相当于css/wx.css,作为要查询的目标文件,{ 'document_root': settings.STATIC_ROOT_WXROOT,}含义是在此路径的下查询XXXX
setting.py中的配置如下:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT_WXROOT=os.path.join(BASE_DIR, "wxroot/static/wxroot")
STATIC_ROOT_ADMIN=os.path.join(BASE_DIR, "static/admin")
其中BASE_DIR相当于/opt/mysite/
配置完成,上传到SAE上,且为Debug=False,再次访问html,已经可以成功加载
Django在SAE上无法使用requests模块进行消息的请求问题--实现Python从在工程路径中加载模块
【问题描述】
想在django上实现如下需求:
用户请求一个网页,网页中部分参数需要从其他的网站获取,django通过requests模块构造请求的消息,并解析响应的内容,把参数赋值到响应给用户的HTML页面中。在本地使用requests模块,可以实现功能,但是上传工程到SAE上就报requests模块不存在的错误,且使用其他的request构造某块如urllib,urllib3等,都报此错误
【原因分析】
初步推断是SAE上的Python环境中缺少此模块,猜测应该是SAE对此功能进行屏蔽
【解决方法】
在网上下载requests的安装包,把解压后的requests文件夹复制到工程路径下的site-packages路径,ruquests的下载路径
http://cn.python-requests.org/
在工程文件index.wcgi中将site-packages添加到系统的path
在需要引用此模块的地方,直接import requests即可
【总结】
不可能在SAE上安装requests模块,根本没有权限访问系统,只能通过SVN实现上传和下载的功能,所以能改变的只有自己的工程文件
如何让将requests安装到工程目录下面,并让python能搜索到呢?
在网上查了一下Python安装和加载模块的原理,发现Python安装模块其实就是将模块复制到对应的路径下下面,可能还涉及一些依赖文件的校验,安装数据库中的信息维护等,但是基本的流程是复制待安装模块到安装路径,对于我的需求仅仅能够实现模块的加载就行,所以就直接在网上下载了requests的安装包,把解压后的requests文件夹复制到django工程下的“site-packages”,就可以正常加载了
Dajngo HTML5实现文件的上传和以及进度反馈
1、整体流程
A、用户在客户端提交上传文件的表单,通过JS实现进度条的功能
B、服务器接收到用户提交的请求后处理请求,并将文件请求中的文件对象保存到服务器
2、引入包
jquery.js
3、客户端页面
<script src="{% static 'wxjs/js/jquery-3.1.1.js' %}"></script>
<script type="text/javascript">
function uploadFile() {//用于提交表单的JS
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
var csrftoken = getCookie('csrftoken');//获取csrftoken用于防csrf攻击
xhr.upload.addEventListener("progress", uploadProgress, false);//添加进度的监听事件
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "/wxroot/JS/upload_file");
xhr.setRequestHeader("X-CSRFToken", csrftoken);//将csrftoken的值写入到post请求的头域中去
xhr.send(fd);
}
function uploadProgress(evt) {#在页面上显示上传的进度
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
。。。。。。
表单如下:
<form id="form1" enctype="multipart/form-data" method="post" action="">
{% csrf_token %} //此处必须加入,用来防止csrf攻击,和post头域中的值csrftoken值是相同的,但是这个值是在服务端生成
<div class="row">
<label for="fileToUpload">Select a File to Upload</label>
<input type="file" name="fileToUpload" id="fileToUpload" οnchange="fileSelected();"/>
</div>
<div class="row">
<input type="button" οnclick="uploadFile()" value="Upload" />
</div>
<div id="progressNumber"></div>
</form>
4、服务器段页面
urls中进行如下配置:
url(r'^imageupload$',views.imageupload),#用于加载表单的页面
url(r'^upload',views.upload_file),#用于处理上传的文件
view中脚本如下:
def upload_file(request): #处理文件上传的试图,将文件写入本地的静态文件夹中
if request.method == "POST": # 请求方法为POST时,进行处理
myFile =request.FILES.get("fileToUpload", None) # 获取上传的文件,如果没有文件,则默认为None
if not myFile:
return HttpResponse("no files for upload!")
destination = open(os.path.join(settings.STATIC_ROOT_WXJS,'media'+myFile.name),'wb+') # 打开特定的文件进行二进制的写操作
for chunk in myFile.chunks(): # 分块写入文件
#destination.write(chunk)
pass
destination.close()
print(myFile.name+str(myFile.size)+myFile.content_type)
return HttpResponse("upload over!")