Categories

Links

django小提示-maxlength,max_length

在django 0.96,CharField的的最大长度使用maxlength
在svn的代码中,这个已经修改为max_length(这样,更符合python一般的命名规范,当然,事实上python并没有像ruby一样对命名规范有严格的要求,比方说unittest,wxpython就使用两个不同的命名规范),但实际上,原先的代码并不会出错,django是如何达成的呢

这里,django 使用了metaclass的功能

1. 首先,查看Field对象的定义,你会发现
class Field(object):
    __metaclass__ = LegacyMaxlength

LegacyMaxLength定义在django.utils.maxlength 模块中,这个metaclass非常简单
class LegacyMaxlength(type):
    def __init__(cls, name, bases, attrs):

        super(LegacyMaxlength, cls).__init__(name, bases, attrs)
        #对构造函数进行修饰
        cls.__init__ = remove_maxlength(cls.__init__)
        #增加maxlength属性    
        cls.maxlength = property(get_maxlength, set_maxlength)

remove_maxlength巧妙的运用了decorate ,对class 构造进行进行处理,流程很简单,就是从参数中取max_length,maxlength,如果有maxlength,则给你个已过期的警告,如果你同时设置了max_length和maxlength,则给你来个错误(因为 django这样无法判断你用 那个),然后将maxlenth设置给max_length,并创建maxlength属性

这样Field class的代码本身就非常干净,并没有为保持兼容性而同时存在maxlength和max_length两个属性. (虽然实际生成的代码还是有两个的,一个是max_length field还有一个是通过metaclass生成的maxlength property)

这里django 巧妙的利用metaclass实现deprecated 功能的.

在django的代码中,对于类似dsl的功能,django主要利用metaclass和descriptor来达成的,比方说model ,django构造了一个ModelBase metaclass,然后让Model使用这个元类,像对于关系处理, ForeignKey最终是将使用ReverseSingleRelatedObjectDescriptor 这样的 descriptor对象,也就是说,当你遇到
class Customer(models.Model):
    shipping_address=models.ForeignKey(Address)

最后,这个类被解释执行后的shipping_address实际上是一个叫shipping_address的ReverseSingleRelatedObjectDescriptor 的实例.

descriptor和metaclass的基本知识,我推荐参阅这这几个链接
How-To Guide for Descriptors
http://users.rcn.com/python/download/Descriptor.htm#static-methods-and-class-methods
我强烈推荐这个文档, 看后你会知道descriptor 包括property,staticmethod,classmethod到底是如何运作的,也会理解bound(bind)在动态语言中的作用.
Python 中的元类编程 -将面向对象编程推向新的高度
http://www.ibm.com/developerworks/cn/linux/l-pymeta/index.html
Python 中的元类编程,第 2 部分- 理解继承的奥秘和实例创建
http://www.ibm.com/developerworks/cn/linux/l-pymeta2/index.html

[2007-11-30 15:17:07 | Author:jiangjianxiao ] [] 4 comments

django小提示-json

django提供了基于json,yaml,xml的串行化支持. 这里我们主要来讲json
django对json 的支持有两个层次
第一个层次在django.utils.simplejson包中 ,JSONEncoder 提供了常见python数据类型像tuple,list,dict,string,float,decimal等的支持,但这里,并不包含对自定义python对象的json支持
第二个层次在django.core.serializers 包中,这个包提供了对json,yaml(如果你安装了pyyaml的话,xml的串行化支持. 注意,在这里,只能串行化querySet,而且,你只能在django项目内部使用(当然你可以通过手动将项目路径加入到sys.path并设置    os.environ["DJANGO_SETTINGS_MODULE"] = myproject.settings' 来在非django项目中使用)


第一个层次可以在其他非django 项目中使用,你需要继承JSONEncoder,并覆盖default方法,比方说你有一个Employee对象

class Employee:
    def __init__(self,name):
        self.name=name

from django.utils.simplejson.encoder import JSONEncoder
class ObjectJSONEncoder(JSONEncoder):
    def default(self,o):
        if hasattr(o,"__dict__")
             return o.__dict__
        return super(ObjectJSONEncoder,self).default(o)

# test

data=[1,{'a':'a'},Employee('jjx')]
import django.utils.simplejson

print django.utils.simplejson.dumps(data,cls=ObjectJSONEncoder)


[1, {"a": "a"}, {"name": "jjx"}]


当使用第二个层次时,你可以通过传递fields 参数选择输出的字段,也可以传入一个io对象

from django.core.serializers import seralize
from cStringIO import StringIO
stream=StringIO()

seralize('json',User.objects.all(),stream=stream,fields=['username'])
print stream.getvalue()

当将json输出到浏览器时,你可以传递mimetype参数为text/json或text/javascript
return HttpResponse(json_str,mimetype="text/json")

update django snippets 上有 个JsonResponse类, 可以参考
http://www.djangosnippets.org/snippets/154/

from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.http import HttpResponse
from django.utils import simplejson

class JsonResponse(HttpResponse):
def __init__(self, object):
if isinstance(object, QuerySet):
content = serialize('json', object)
else:
content = simplejson.dumps(object)
super(JsonResponse, self).__init__(content, mimetype='application/json')
[2007-11-28 16:37:21 | Author:jiangjianxiao ] [] 4 comments

django小提示-打印sql语句

当settings.Debug=True时,django 使用的是django.db.backets.util.CursorDebugWrapper ,这样,当你执行execute,executemany时,django会把你执行的语句加入到BaseDatabaseWrapper派生对象的queries列表,每次加入的是一个dict,包括sql和time
这样,你可以在任何时候打印connection对象的queries属性或是直接在CursorDebugWrapper的execute和executemany中加入print语句

def execute(....):
    ...
    print smart_unicode(sql) % convert_args(params),"%.3f" % (stop - start)

在django中connection对象实际上就是BaseDatabaseWrapper的派生类
看这行
connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)

再看backend模块是怎么来的
    _import_path = 'django.db.backends.'
    backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, [''])

显然,如果你的DATABASE_ENGINE为mysql的话,这个导入语句就是
__import("django.db.backends.mysql.base",{},{},[''])

通常,mysqldb的cursor执行结果为一个tuple ,虽然这样效率较高,但有时 也不方便,你可以让 在创建真实的mysqldb connection对象时传入cursorclass参数

修改django.db.backends.mysql.base.DatabaseWrapper
def _cursor(...):
            #keargs['cursorclass']=Database.DictCursor # 加上这行
            self.connection = Database.connect(**kwargs)

或者在settings.py中增加
import MySQLdb
CURSOR_CLASS=MySQLdb.Cusor # 或者CURSOR_CLASS=MySQLdb.DictCursor

然后
def _cursor(...):
           keargs['cursorclass']=settings.CURSOR_CLASS # 加上这行
            self.connection = Database.connect(**kwargs)

你也可以修改
  cursor = self.connection.cursor() 为
  cursor = self.connection.cursor(settings.CURSOR_CLASS)
效果是一样的

[2007-11-28 11:05:03 | Author:jiangjianxiao ] [] 2 comments

asp.net mvc笔记- 替换自己的view engine,依赖注入

使用自己的view引擎


asp.net mvc 的view引擎提供对asp.net page,usercontrol 的的支持. 你还可以创建自己的view引擎,过程非常简单1. 实现IView接口,比方说
public class NVelocityView : IView
{
    public string ViewName
    {
        get;
        set;
    }
    public string MasterName
    {
        get;
        set;
    }
    public object ViewData
    {
        get;
        set;
    }
   
    public void RenderView(ViewContext viewContext)
    {
        //用nvelocity解析模板,这个任务留给大家完成
        string context = string.Empty;
        context = "解析后的内容";

        viewContext.HttpContext.Response.Write(context);

    }

}

2. 实现IViewFactory接口
public class NVelocityViewFactory : IViewFactory
{
   

    public IView CreateView(ControllerContext controllerContext, string viewName, string masterName, object viewData)
    {

        return  new NVelocityView { ViewName = viewName ,MasterName=masterName,ViewData=viewData};
       
      
    }

 
}
3. 继承Controller类,在类构造中设置ViewFactory参数
public class HomeController : Controller
{
    public HomeController()
    {
        ViewFactory = new NVelocityViewFactory();
    }
    [ControllerAction]
    public void Index()
    {
    }
}

依赖注入

4. 实现 IControllerFactory
在这里进行依赖注入,比方说调用
public class SpringControlFactory : IControllerFactory
{

 
    public IController CreateController(RequestContext context, System.Type controllerType)
    {
        string requiredString = (string)context.RouteData.Values["controller"];
        return (IController)ContextRegistry.GetContext()[requiredString];

    }

}
5. 设置controlerfactory
代码放到global.asax 的Application_Start中
 
ControllerBuilder.Current.SetDefaultControllerFactory( typeof(SpringControlFactory));
更新 ControllerBuilder提供了SetControllerFactory和SetDefaultControllerFactory两个方法, 通常,SetControllerFactory是针对特定的controller类型的, 在这个场景,你想对所有的controller子类生效,就用 SetDefaultControllerFactory

通过依赖注入,我们可以在外部实现修改ViewFactory的功能
<object id="myViewFactory" type="xxx.NVelocityViewFactory,xxx"/>
<object id='Home' type="xxx.HomeController,xxx" singleton="false">
<property name="ViewFactory" ref="myViewFactory"/>
</object>

IControllerFactory 非常重要, 这里,你可以使用dlr ,整合ironpython和ironruby,因为你已经得到controller名,接下来你可以从文件系统中读取对应的ironpython或ironruby 文件,编译和执行它,返回给asp.net mvc
这个链接 描述了如何host ironruby 2.0 r6
http://blogs.msdn.com/rdawson/archive/2007/11/29/hosting-ironpython-2-0-alpha-6-via-the-dlr.aspx
而codeplex 上有个nwsgi 项目, 你可以参考如何使用ironpython来达成在asp.net实现一个wsgi实现的


大家可以看到,继承自己的view引擎和ioc功能和整合动态语言是非常简单的, asp.net mvc 只是提供了一个简单的层次.对于类似castle 项目,两者更多的是互补而不是竞争.比方说castle的route功能不强 ,orm 不足,更多的是缺少社区的关注.  利用asp.net mvc ,castle 可以更多的将眼光关注到具体的领域问题上.


[2007-11-26 18:03:58 | Author:jiangjianxiao ] [] 3 comments

nwsgi

nwsgi是一个asp.net 上的wsgi实现(使用asp.net ihttphandler), 这样,理论上,你可以在asp.net 使用那些wsgi兼容的python web framework . 当然,最终能不能用,还是要看ironpython .一般来说,没有和c扩展交互的python应用,大部分可以顺利运行. 作者的例子中也用了paste/cherrypy. 不过至于django/pylons 之类的,就别想了.

这项目还没有release,你可以从sourcecode中下载.如果打算用ironpython 做自己的web框架,使用nwsgi+paste或许是个不错的起点

下载地址
http://www.codeplex.com/NWSGI
[2007-11-14 15:21:19 | Author:jiangjianxiao ] [] 1 comments

Total 91 Display 6 of 10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Powered by Google App Engine