SAE Django+WeChat环境开发手记--持续更新

来源:互联网 发布:德国小蠊特效药 淘宝 编辑:程序博客网 时间:2024/05/21 17:32

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.pyfrom django.contrib import adminadmin.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.yamlhandlers:- url: /foo  static_dir: foo
修改完成后SAE上就可以正常访问HTML,js文件也都可以正常加载了

总结:此方法只能在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" onchange="fileSelected();"/>
</div>
<div class="row">
<input type="button" onclick="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!") 


0 0