对于稍微复杂些的DNN模块,参考Manifest清单文件的相关节点信息可简易打包最易管理的模块安装包。比如可参考大神Bruce Chapman提到的以下5点:

Top 5 DotNetNuke Manifest file Module Packaging Tips

  1. Use Html in the File for better layout in the install pages
  2. Use a resources.zip file for all your files
  3. Use a html file for your Licence Agreement
  4. Make your module DNN 4.x and DNN5.x compatible by using two separate manifest files.
  5. Use the ‘sourceFileName’ attribute for your assembly files.

其他官方文档可参考如下链接:

Types of Manifests

The DNN Manifest Schema

目前发现releasenotes这一节点只能这样用:

<releaseNotes src="Installation\ReleaseNotes\Release.07.03.00.txt"></releaseNotes>

错误的用法:

<releaseNotes>
    <releaseNote src="Installation\ReleaseNotes\Release.07.03.00.txt"/>
</releaseNotes>

利用Virtualenv搭建Django环境

  1. 确保安装Python3,请参照python2和python3共存win7的解决方案。
  2. 创建虚拟环境, 创建目录py3env

    python3 -m venv py3env
    
  3. 定位到目录py3env\scripts并激活虚拟环境:

    E:\virt_env\py3env\Scripts>activate
    (py3env) E:\virt_env\py3env\Scripts>
    
  4. 手动安装Django

    pip install django==1.9.6
    

    或直接clone项目到本目录下E:\virt_env\py3env\Scripts>并定位到项目目录下执行:

    pip install -r requirements.txt
    

    requirements.txt文件,主要用于搭建运行这个项目所需要的环境,一般包含项目所需的一些包的名称和版本之类的信息。

Django基本命令

  1. 运行命令 python manage.py makemigrations 生成迁移文件

  2. 运行命令 python manage.py migrate 迁移数据库

  3. 运行命令 python manage.py createsuperuser 创建超级用户

  4. 运行命令 python manage.py runserver 启动开发服务器

参考资源

Django 1.8.2 文档
Django 基础教程
Virtualenv官网文档
Python Virtualenv 介绍

基于Vagrant搭建全栈式的Python开发环境

What is Vagrant?

vagrant是建立在虚拟机基础上的虚拟环境管理工具。可用于快速创建基于VirtualBox、VMware、AWS的虚拟机,提供易于配置,重复性好,便携式的工作环境。也可以和puppet,chef结合,实现虚拟机管理的自动化。

对于前提——虚拟机,官方推荐使用VirtualBox,因为免费/容易获取/支持各平台/vagrant内嵌。

对于被管理的对象——虚拟环境,vagrant就是为了避免创建虚拟机繁琐的过程而出现的,它将一个虚拟环境封装为一个基础镜像,并给了一个生动的名字——box,所以这里的虚拟环境就是box。而管理,也就是添加,使用,销毁这些操作了。

vagrant安装

https://www.vagrantup.com

https://www.virtualbox.org/wiki/Downloads

vagrant基本命令行

  1. vagrant init

    一个普通的目录要成为vagrant可用的目录,需要初始化一下。初始化之后可以发现在目录下多了一个Vagrantfile文件,查看此文件,发现有很多被注释的配置示例,请参照《Vagrantfile基本配置文件详解》修改。

  2. vagrant box add

    目前我们只是拥有一个vagrant可用的目录。下一步自然是需要一个虚拟环境,在box列表中没有所需的虚拟环境时可以这么做:HashiCorp’s Atlas box catalog里聚集了各种可用的box,进入挑选一番,比如说看中了ubuntu/trusty64,在终端运行vagrant box add ubuntu/trusty64,vagrant会从服务器下载ubuntu/trusty64并添加进box列表,可用vagrant box list查看。当然也可以手动将box下载至本地,再添加vagrant box add boxname ~/box/ubuntu/trusty64。一般建议执行本地添加box。

  3. vagrant up

    一切就绪,启动虚拟环境,打开virtual box可以发现该虚拟机已启动。

  4. vagrant ssh

    以ssh登录虚拟环境,OK,已进入box,之后就可以通过终端在你的虚拟环境里做任何事情了

  5. vagrant reload

    重新加载当前虚拟环境。如果你修改了vagrantfile配置项后,一般需要执行此操作来更新起效。

  6. vagrant halt

    挂起,顾名思义,关闭当前虚拟环境。

  7. vagrant destroy

    彻底销毁当前虚拟环境。慎用。

  8. vagrant package

    可对当前虚拟环境打个包,不仅能存下当前环境,还能随身带随时用。其他用户只要添加这个box,用其初始化自己的开发目录就能得到一个一模一样的虚拟开发环境了。

  9. vagrant box remove virtualbox_name

    删除本地指定名称的box,可通过vagrant box list得到当前所有存在的box名称里列表。

Vagrantfile基本配置文件详解

Vagrant使用Ruby开发,所以它的配置语法也是Ruby的。
修改完Vagrantfile配置后,必须用vagrant reload重启VM后,配置才能生效。

  1. 配置基本说明

    Vagrant.configure(2) do |config|
    #......
    end
    

    configure(“2”)描述的是使用Vagrant 2.0.x配置方式。
    Vagrant 1.0.x的配置方式为:Vagrant::COnfig.run do |config| …

  2. box设置

    config.vm.box = "boxIdentity"
    

    配置Vagrant要去启用哪个box作为系统

  3. hostname设置

    config.vm.hostname = "go-app"
    

    host用于识别虚拟主机。特别在有多台虚拟机时,务必进行设置。

  4. 网络设置

    Vagrant有两种方式进行网络连接.
    (1)host-only主机模式,意思是主机与虚拟机之间的网络互访。其他人访问不到你的虚拟机。
    (2)bridge桥接模式,此模式下VM如同局域网中的一台独立的直接虚拟机,可以被其他机器访问。

    config.vm.network: private_network, ip: "192.168.33.11"
    

    这里设置为host-only模式,且虚拟机ip设置为”192.168.33.11”

  5. 端口转发

    Vagrant会默认初始化一个端口映射为guest:22, host:2222 也就是说客户机的22端口,将被映射到宿主机的2222端口

    config.vm.network: forwarded_port, guest: 8080, host: 5000
    

    而以上设置将主机上的5000端口forward到虚拟机的8080端口上。

    注意:linux在开启1024(不含1024)之前端口时是需要root权限的。所以一般建议在虚拟机上分配1024以上的端口。

  6. 同步目录

    除了默认的/vagrant同步目录外,还可以设置额外的同步目录:

    config.vm.synced_folder "d:/local/dir", "/vagrant_data/"
    

    第一个参数是本地目录,第二个参数为虚拟机目录。

Ubuntu安装pip和virtualenv

$ sudo apt-get install python-pip python-dev build-essential
$ sudo pip install --upgrade pip
$ sudo pip install --upgrade virtualenv

Ubuntu安装git

sudo apt-get install git

Ubuntu安装Web.py

sudo easy_install web.py

执行完之后进入pytohn解释器输入

>>>import web
>>>

如果没有出现错误提示(如上)那就证明安装配置成功了。

Ubuntu安装Flask

sudo apt-get install python-flask

注意:在虚拟机中,创建 Flask App 的时候,修改调用run()的方法使服务器公开可用,让操作系统监听所有公网 IP。不然你没法在主机访问到虚拟机对的web app。

app.run(host='0.0.0.0')

详细代码如下:

from flask import Flask  
app = Flask(__name__)  

@app.route('/')  
def hello_world():  
    return 'Hello World!'  

if __name__ == '__main__':  
    app.run("0.0.0.0", debug=True)

What is selenium?

Selenium 是一个可以让浏览器自动化地执行一系列任务的工具,常用于自动化测试

Selenium安装

参照另外一教程文章Windows下Python easy_install和pip的安装:

easy_install selenium 

范例一:网页截图

#!/usr/bin/env python
# coding: utf-8

import os, sys, time, datetime
import urllib
import urllib2
from selenium import webdriver

reload(sys)
sys.setdefaultencoding('utf-8')

def mock_screenshot(url, width, height, imgPath = 'screenshot.png'):
    # browser = webdriver.PhantomJS('E:\Downloads\phantomjs-1.9.7-windows\phantomjs.exe')  #浏览器初始化;Win下需要设置phantomjs路径,linux下置空即可
    browser = webdriver.Firefox()
    browser.set_window_size(width, height) #参考当前PC的分辨率
    browser.get(url)  # 打开网页

    browser.execute_script("""
        (function () {
          var y = 0;
          var step = 100;
          window.scroll(0, 0);

          function f() {
            if (y < document.body.scrollHeight) {
              y += step;
              window.scroll(0, y);
              setTimeout(f, 50);
            } else {
              window.scroll(0, 0);
              document.title += "scroll-done";
            }
          }

          setTimeout(f, 1000);
        })();
      """)

    for i in xrange(1024):
        if "scroll-done" in browser.title:
          break
        time.sleep(1)

    browser.save_screenshot(imgPath)

    browser.quit()  # 关闭浏览器。当出现异常时记得在任务浏览器中关闭PhantomJS,因为会有多个PhantomJS在运行状态,影响电脑性能

注意到,上面的代码中,并没有在打开页面后立即截图,而是先在页面上执行了一段Javascript脚本,先将页面的滚动条拖到最下方,再拖回顶部,然后才截图。这样的好处是如果页面下方有一些ajax延迟加载的内容,在这个操作之后一般其他内容也都已加载了,如此截图才完整些。

范例二:模拟鼠标点击等行为

由范例一我们可以举一反三,我们可以执行某一段js脚本或ajax请求以获取指定或我们想要的内容,甚至模拟鼠标点击等行为让浏览器自动化地执行某些操作。

# other coding above

browser.get(url)  # 打开网页

jsActionElem = browser.find_element_by_class_name('tit_a')

jsActionElem.click()

# other coding continuing ...

免费可用的DNN模块

收集一些比较优秀的开源模块,其中包括官方原本提供服务支持的模块。

还有一些来源于原本开发DNN商业模块的部分公司,由于业务转型需要不再专注DNN平台,故此之前售卖的DNN模块也因此开发源代码供客户下载,其中包括dnnspot等:

创建永久链接

只在7.4.1+版本提供支持,通过PageBase.CanonicalLinkUrl这一属性来设置。

一般模块开发需要设置属性获得PageBase:

public DotNetNuke.Framework.CDefault BasePage {
    get { return (DotNetNuke.Framework.CDefault)this.Page; }
}

再应用如下:

//set the CanonicalLinkUrl property of the page 
this.BasePage.CanonicalLinkUrl = canonicalUrl;

来源Create a Canonical Url Link in Dnn by using the CanonicalLinkUrl property

刪除管理页面的全局模块

有时可能需要在页面顶部或底部增加一些全局模块,比如Social twitter或最新新闻等,勾选该模块的Settings设置项[Display Module On All Pages?]即可。不过这样的后果则是管理页面Admin下的所有页面也添加了这些模块,其实这是没有必要的。只好手动删除,进入Host->SQL页面:

选择数据并核实:

SELECT t.TabPath, tm.* FROM TabModules tm
LEFT JOIN Tabs t ON t.TabID = tm.TabID
WHERE tm.ModuleID = 842 AND t.TabPath LIKE '//Admin//%'

删除之:(谨慎并确保备份数据库)

DELETE tm FROM TabModules tm
LEFT JOIN Tabs t ON t.TabID = tm.TabID
WHERE tm.ModuleID = 842 AND t.TabPath LIKE '//Admin//%'

可能需要清除缓存Tool->Clear Cache.

清除异常日志ImageChallenge.captcha.aspx

在Admin-Event Viewer页面你会经常看到很多关于ImageChallenge.captcha.aspx的异常日志,错误信息大概类似:

AssemblyVersion: 7.3.1
PortalID: -1
PortalName:
UserID: -1
UserName:
ActiveTabID: -1
ActiveTabName:
RawURL: /desktopmodules/admin/security/ImageChallenge.captcha.aspx?captcha=D6D87243DABF349C49DC324DFC2B66F8E1ADDBD1356F4140AA170E03C77B055A91DFA47C90A054E011E6FE732E95BB7767BC671D2428C808FC5C27E736428EBDEB2CFCBDF70FBFBBCD8C8B28DFDF8436FFACF3F9997CF30A9E04753C212D362C64EFCF66662B11FC17D014B5028FAF02895DB78AE8C6F4CDF84EE10D249D29B5F46D96EA7E4109A5F03DFFDC0BFD2A2C94CBFE8D0B3A98F892585E18EFBDEBB9AF3BF3C6&alias=www.tarighat-music.com
AbsoluteURL: /desktopmodules/admin/security/ImageChallenge.captcha.aspx
AbsoluteURLReferrer:
UserAgent: Googlebot-Image/1.0
DefaultDataProvider: DotNetNuke.Data.SqlDataProvider, DotNetNuke.SqlDataProvider
ExceptionGUID: 58496425-d653-4fcd-aef3-cbec0a5bf8d9
InnerException: Input string was not in a correct format.
FileName:
FileLineNumber: 0
FileColumnNumber: 0
Method: System.Number.StringToNumber
StackTrace:
Message: System.FormatException: Input string was not in a correct format. at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) at DotNetNuke.UI.WebControls.CaptchaControl.GenerateImage(String encryptedText )

目前在DNN7+版本下的解决方案是把下列信息添加到网站根目录下的文件robots.txt里:

User-agent: Googlebot
Disallow: *captcha*       # remove captcha images that resolve as pages

参考链接:

ImageChallenge.captcha.aspx System.FormatException is flooding the log

依然持续关注并开发DNN产品的公司及人员

http://www.iowacomputergurus.com
http://www.bitethebullet.co.uk/
http://www.dotnetnukeblogs.com/
http://mitchelsellers.com/
https://github.com/mitchelsellers
http://dnnextension.com/
http://www.5stonesmedia.com/blog
大牛Shaun Walker(DNN创始人)的博客

Teamviewer现在无法捕捉屏幕

根源或原因

Teamviewer现在无法捕捉屏幕,这可能是由于快速的用户切换或远程桌面会话已经断开。

这是由于你用“远程桌面”连过去开启teamview的话,当你退出“远程桌面”后,外网用teamview连接就会出现这个问题,

解决方法:

不用远程连接过去开启teamview,直接在在电脑本机上手动开启teamview就可以了
或重启受控方的电脑或服务器即可:shutdown -r -t 0

为何要安装easy_install和pip

easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的

正常情况下,我们要给Python安装第三方的扩展包,我们必须下载压缩包,解压缩到一个目录,然后命令行或者终端打开这个目录,然后执行

setup.py build
setup.py install

来进行安装。这样是不是很繁琐呢?如果我们直接命令行执行

easy_install libname

就把最新版的扩展包libname安装上去了,是不是很爽呢?
所以easy_install就是为了我们安装第三方扩展包更容易

同理,pip可认为是easy_install的替代品。

如何安装easy_install和pip

方法1:

1.首先找到easy_install正确的版本进行下载,下载地址:

http://pypi.python.org/pypi/setuptools

比如win7 32位可以下载setuptools-0.6c11.win32-py2.7.exe

或下载ez_setup.py进行安装,在该文件目录上打开cmd命令行或终端执行

python ez_setup.py

2.安装完成后python的安装目录中会生成scripts目录,其中包括easy_install.exe,然后把该目录添加到Windows系统的环境变量Path里。

方法2:

可直接cmd命令行或终端执行来远程安装:

python ez_setup.py

安装pip:

pip下载地址:https://pypi.python.org/pypi/pip

参考链接:

http://jingyan.baidu.com/article/b907e627e78fe146e7891c25.html

何为Sublime Text

Sublime Text是一个轻量、简洁、高效、跨平台的编辑器。Sublime Text更妙的是它的可扩展性,它拥有强大的插件支持,几乎无所不 能。目前已经更新到Sublime Text 3支持OS X、Windows、Windows 64 bit、Ubuntu 64 bit和 Ubuntu 32 bit。免费下载、超快速超稳定,可以处理大量超大文件。总之,这是一款神器级别的代码编辑器。

参考资料:

http://www.iplaysoft.com/sublimetext.html

安装Package Control

1.通过快捷键 ctrl+`(Esc键下边或跟~公用的) 或者 View > Show Console 打开控制台,然后粘贴相应的安装代码(Python代码),从官方网站可获取, 比如#st2:

import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')

2.回车运行安装代码。

3.重启Sublime Text 2/3。

4.如果在Perferences->package settings中看到package control这一项,则安装成功。

利用Package Control安装插件

1.按下Ctrl+Shift+P调出命令面板

2.输入install调出Install Package选项并回车,然后在列表中搜索或选中要安装的插件。如图:
Pakcage Control: Install Package

3.根据网络速度不同Package加载时间不等,稍等片刻即可安装指定插件。

Python开发插件

  • SublimeCodeIntel 智能提示插件,为部分语言增强自动完成功能,包括Python 。这个插件同时也可以让你跳转到符号定义的地方,通过按住alt 并点击符号,非常方便。
  • SublimeREPL Python调试插件。可将Sublime Text布局模式切换为2行模式(Shift+Alt+8),然后tool->SublimeREPL->Python->Python - PDB Current File打开pdb调试界面。然后你就可以输出各种pdb命令进行调试了。比如:

    (Pdb) b 31              #在31行建立断点
    (Pdb) r                 #运行到断点处
    (Pdb)                   #在这个命令行下就可以执行当前上下文的python
    

其他相关问题

1.弹出错误信息:
A plugin (SublimeCodeIntel) may be making Sublime Text unresponsive by taking too long (0.020000s) in its on_modified callback.
This message can be disabled via the detect_slow_plugins setting

解决方法:打开preference->setting_user
添加

"detect_slow_plugins": false

这样以后就不会弹出类似提示了。

  1. php代码自动提示与补全设置

解决方法:打开preference->setting_user
添加

"auto_complete": true,
"auto_match_enabled": true

获取数组交集

#方法一:
a=[2,3,4,5]
b=[2,5,8]
tmp = [val for val in a if val in b]
print tmp
#[2, 5]

#方法二
print list(set(a).intersection(set(b)))

获取数组并集 (合并去重)

print list(set(a).union(set(b)))

获取数组差集

print list(set(b).difference(set(a))) # b中有而a中没有的

利用PIL比较两个图片的相似度

需要安装PIL图像模块,代码虽短但效果不错,还是非常靠谱的,前提是图片要大一些,太小的图片不好比较, 代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import Image, sys, os

reload(sys)
sys.setdefaultencoding('utf-8')

def make_regalur_image(img, size = (256, 256)):
    return img.resize(size).convert('RGB')

def split_image(img, part_size = (64, 64)):
    w, h = img.size
    pw, ph = part_size

    assert w % pw == h % ph == 0

    return [img.crop((i, j, i+pw, j+ph)).copy() \
                for i in xrange(0, w, pw) \
                for j in xrange(0, h, ph)]

def hist_similar(lh, rh):
    assert len(lh) == len(rh)
    return sum(1 - (0 if l == r else float(abs(l - r))/max(l, r)) for l, r in zip(lh, rh))/len(lh)

def calc_similar(li, ri):
#   return hist_similar(li.histogram(), ri.histogram())
    return sum(hist_similar(l.histogram(), r.histogram()) for l, r in zip(split_image(li), split_image(ri))) / 16.0

def calc_similar_by_path(lf, rf):
    li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
    return calc_similar(li, ri)

def make_doc_data(lf, rf):
    li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
    li.save(lf + '_regalur.png')
    ri.save(rf + '_regalur.png')
    fd = open('stat.csv', 'w')
    fd.write('\n'.join(l + ',' + r for l, r in zip(map(str, li.histogram()), map(str, ri.histogram()))))
#   print >>fd, '\n'
#   fd.write(','.join(map(str, ri.histogram())))
    fd.close()
    import ImageDraw
    li = li.convert('RGB')
    draw = ImageDraw.Draw(li)
    for i in xrange(0, 256, 64):
        draw.line((0, i, 256, i), fill = '#ff0000')
        draw.line((i, 0, i, 256), fill = '#ff0000')
    li.save(lf + '_lines.png')

if __name__ == '__main__':
    path = u'E:\\data\\tmp' 
    toPath = u'E:\\data\\tmp'

    path = path.replace('\\', '/')
    toPath = toPath.replace('\\', '/')

    print 'start compare similar....'
    for x in os.listdir(path):
        for y in os.listdir(toPath):
            if x == y:
                continue

            degree = calc_similar_by_path(os.path.join(path,x), os.path.join(toPath,y))
            if degree > 0.6:
                print 'similar so much in test_case (%s <-> %s): %.3f%%'%(x, y, degree * 100)
                # make_doc_data(x, y)

    print 'end compare similar....'