pyramid学习笔记3-创建注册页面
来源:互联网 发布:郑州美好电子淘宝店 编辑:程序博客网 时间:2024/04/29 03:01
Pyramid可以为资源、路由、静态资源产生URL,pyramid有一个统一的view callables概念,view callables可以是函数、类的方法,或者一个实例。顾名思义,view callables就是让这个view callable处理对应的view URL页面。在mypriject->view->views.py添加/user/regist注册view callables:
#coding=utf-8from pyramid.view import view_defaults,view_configfrom myproject.api.validator import *from myproject.api.simpleform import Form,Statefrom logging import getLoggerlog = getLogger(__name__)def includeme(config): config.scan(__name__) config.add_route('user', '/user/{action}') config.add_route('event', '/event/{action}') @view_defaults(route_name='user')class UserView(object): def __init__(self, request): self.request = request self.db=request.db @view_config(renderer='user/regist.mako', match_param=('action=regist'), request_method='GET') @view_config(renderer='jsonp', match_param=('action=regist'), request_method='POST') def regist(self): if self.request.method=="POST": validators = dict( phone = PhoneNumber(), name = RealName(), password = Password() ) form = Form(self.request, validators=validators, state=State(request=self.request), variable_decode=True) if form.validate(force_validate=True): log.debug(form.data) if self.db.user.find_one({'phone':form.data.get('phone')}): return dict(error='该号码已经注册') if form.data.get('name')=='习近平': return dict(error='姓名中不能有敏感词汇') self.db.user.save({'phone':form.data.get('phone'), 'name':form.data.get('name'), 'password':form.data.get('password')}) return {} @view_defaults(route_name='event')class EventView(object): def __init__(self, request): self.request = request @view_config(renderer='event/create.mako', match_param=('action=create'), request_method='GET') def create(self): return {}以上用到了pyramid.config和pyramid.view模块,详细说明参考官方文档:
http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/latexindex.html#api-reference
logging模块用于开发调试用,myproject.api.simpleform和validator用于前台数据验证,这里我们自己封装了api。在myproject下新建api包:创建__init__.py,validator.py和simpleform.py文件:
validator.py
#coding=utf-8import formencode as feimport refrom bson.objectid import ObjectId_ = lambda s: sclass PhoneNumber(fe.FancyValidator): def _convert_to_python(self, value, state): validator = fe.validators.Regex(r'^(13|15|18)\d{9}$') value = validator.to_python(value, state) return value _to_python = _convert_to_pythondef Password(*kw, **kwargs): return fe.validators.String(min=6, max=20)def RealName(*kw, **kwargs): return fe.validators.UnicodeString(min=2, max=10)这里用到了formcode模块,详细参考官方网站:
http://www.formencode.org/en/latest/
由于MongoDB是采用bson的形式存储数据的,所以引入bson模块的ObjectId对文档的id进行转换。
simpleform.py
#coding=utf-8import warningsfrom formencode import htmlfillfrom formencode import variabledecodefrom formencode import Invalidfrom formencode.api import NoDefaultfrom pyramid.i18n import get_localizer, TranslationStringFactory, TranslationStringfrom pyramid.renderers import renderclass State(object): """ Default "empty" state object. Keyword arguments are automatically bound to properties, for example:: obj = State(foo="bar") obj.foo == "bar" """ def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) def __contains__(self, k): return hasattr(self, k) def __getitem__(self, k): try: return getattr(self, k) except AttributeError: raise KeyError def __setitem__(self, k, v): setattr(self, k, v) def get(self, k, default=None): return getattr(self, k, default)fe_tsf = TranslationStringFactory('FormEncode')def get_default_translate_fn(request): pyramid_translate = get_localizer(request).translate def translate(s): if not isinstance(s, TranslationString): s = fe_tsf(s) return pyramid_translate(s) return translateclass Form(object): """ Legacy class for validating FormEncode schemas and validators. :deprecated: 0.7 `request` : Pyramid request instance `schema` : FormEncode Schema class or instance `validators` : a dict of FormEncode validators i.e. { field : validator } `defaults` : a dict of default values `obj` : instance of an object (e.g. SQLAlchemy model) `state` : state passed to FormEncode validators. `method` : HTTP method `variable_decode` : will decode dict/lists `dict_char` : variabledecode dict char `list_char` : variabledecode list char Also note that values of ``obj`` supercede those of ``defaults``. Only fields specified in your schema or validators will be taken from the object. """ default_state = State def __init__(self, request, schema=None, validators=None, defaults=None, obj=None, extra=None, include=None, exclude=None, state=None, method="POST", variable_decode=False, dict_char=".", list_char="-", multipart=False, ignore_key_missing=False, filter_extra_fields=True): self.request = request self.schema = schema self.validators = validators or {} self.method = method self.variable_decode = variable_decode self.dict_char = dict_char self.list_char = list_char self.multipart = multipart self.state = state self.ignore_key_missing = ignore_key_missing self.filter_extra_fields = filter_extra_fields self.is_validated = False self.errors = {} self.data = {} if self.state is None: self.state = self.default_state() if not hasattr(self.state, '_'): self.state._ = get_default_translate_fn(request) if defaults: self.data.update(defaults) if obj: fields = self.schema.fields.keys() + self.validators.keys() for f in fields: if hasattr(obj, f): self.data[f] = getattr(obj, f) def is_error(self, field): """ Checks if individual field has errors. """ return field in self.errors def all_errors(self): """ Returns all errors in a single list. """ if isinstance(self.errors, basestring): return [self.errors] if isinstance(self.errors, list): return self.errors errors = [] for field in self.errors.iterkeys(): errors += self.errors_for(field) return errors def errors_for(self, field): """ Returns any errors for a given field as a list. """ errors = self.errors.get(field, []) if isinstance(errors, basestring): errors = [errors] return errors def validate(self, force_validate=False, params=None): """ Runs validation and returns True/False whether form is valid. This will check if the form should be validated (i.e. the request method matches) and the schema/validators validate. Validation will only be run once; subsequent calls to validate() will have no effect, i.e. will just return the original result. The errors and data values will be updated accordingly. `force_validate` : will run validation regardless of request method. `params` : dict or MultiDict of params. By default will use **request.POST** (if HTTP POST) or **request.params**. """ assert self.schema or self.validators, \ "validators and/or schema required" if self.is_validated: return not(self.errors) if not force_validate: if self.method and self.method != self.request.method: return False if params is None: if not force_validate and self.method == "POST": params = self.request.POST else: params = self.request.params if self.variable_decode: decoded = variabledecode.variable_decode( params, self.dict_char, self.list_char) else: decoded = params self.data.update(decoded) if self.schema: self.schema.ignore_key_missing = self.ignore_key_missing try: self.data = self.schema.to_python(decoded, self.state) except Invalid, e: self.errors = e.unpack_errors(self.variable_decode, self.dict_char, self.list_char) if self.validators: for field, validator in self.validators.iteritems(): value = decoded.get(field) if value is None: try: if_missing = validator.if_missing except AttributeError: if_missing = NoDefault if if_missing is NoDefault: if self.ignore_key_missing: continue try: message = validator.message('missing', self.state) except KeyError: message = self.state._('Missing value') self.errors[field] = unicode(message) else: value = if_missing try: self.data[field] = validator.to_python(value, self.state) except Invalid, e: self.errors[field] = unicode(e) self.is_validated = True return not(self.errors) def bind(self, obj, include=None, exclude=['access_token']): """ Binds validated field values to an object instance, for example a SQLAlchemy model instance. `include` : list of included fields. If field not in this list it will not be bound to this object. `exclude` : list of excluded fields. If field is in this list it will not be bound to the object. Returns the `obj` passed in. Note that any properties starting with underscore "_" are ignored regardless of ``include`` and ``exclude``. If you need to set these do so manually from the ``data`` property of the form instance. Calling bind() before running validate() will result in a RuntimeError """ if not self.is_validated: raise RuntimeError, \ "Form has not been validated. Call validate() first" if self.errors: raise RuntimeError, "Cannot bind to object if form has errors" items = [(k, v) for k, v in self.data.items() if not k.startswith("_")] fields = [] if self.schema: fields = fields + self.schema.fields.keys() if self.validators: fields = fields + self.validators.keys() for k, v in items: if self.filter_extra_fields and fields and k not in fields: continue if include and k not in include: continue if exclude and k in exclude: continue if isinstance(obj, dict): obj.update({k:v}) else: setattr(obj, k, v) return obj def htmlfill(self, content, **htmlfill_kwargs): """ Runs FormEncode **htmlfill** on content. """ charset = getattr(self.request, 'charset', 'utf-8') htmlfill_kwargs.setdefault('encoding', charset) return htmlfill.render(content, defaults=self.data, errors=self.errors, **htmlfill_kwargs) def render(self, template, extra_info=None, htmlfill=True, **htmlfill_kwargs): """ Renders the form directly to a template, using Pyramid's **render** function. `template` : name of template `extra_info` : dict of extra data to pass to template `htmlfill` : run htmlfill on the result. By default the form itself will be passed in as `form`. htmlfill is automatically run on the result of render if `htmlfill` is **True**. This is useful if you want to use htmlfill on a form, but still return a dict from a view. For example:: @view_config(name='submit', request_method='POST') def submit(request): form = Form(request, MySchema) if form.validate(): # do something return dict(form=form.render("my_form.html")) """ extra_info = extra_info or {} extra_info.setdefault('form', self) result = render(template, extra_info, self.request) if htmlfill: result = self.htmlfill(result, **htmlfill_kwargs) return result
然后修改myproject下的__init__.py(不是view下的__init__.py):
from pyramid.config import Configuratorfrom pyramid.renderers import JSONPfrom pyramid.security import unauthenticated_useridfrom bson.objectid import ObjectIdfrom bson.dbref import DBReffrom urlparse import urlparseimport pymongo, datetimedef main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ #using config config = Configurator(settings=settings) #add static view config.add_static_view('static', 'static', cache_max_age=3600) #add jsonp jsonp = JSONP(param_name='callback') jsonp.add_adapter(ObjectId, objectid_adapter) jsonp.add_adapter(DBRef, dbref_adapter) config.add_renderer('jsonp', jsonp) #add request property config.set_request_property(get_db, "db", reify=True) #config.set_request_property(get_user, "user", reify=True) config.include("myproject.view.views") config.scan() return config.make_wsgi_app()def objectid_adapter(obj, request): return str(obj)def dbref_adapter(obj, request): return {'$id': obj.id}'''def get_user(request): userid = unauthenticated_userid(request) if userid is not None and ObjectId.is_valid(userid): user = request.db.user.find_one({'_id': ObjectId(userid)}) if user and user.get('status') == 2: return User(user)'''def get_db(request): settings = request.registry.settings db_url = urlparse(settings['mongo_uri']) conn = pymongo.MongoClient(host=db_url.hostname, port=db_url.port) db = conn[db_url.path[1:]] if db_url.username and db_url.password: db.authenticate(db_url.username, db_url.password) return db
为mako创建通用模板templates/template.mako:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn" xmlns:tal="http://xml.zope.org/namespaces/tal" ><head> <title>时刻</title> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="" /> <meta name="description" content="" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.4.2/pure-min.css"> <link rel="stylesheet" type="text/css" href="/static/css/style.css"> <!--[if lt IE 9]> <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script><![endif]--> <script type="text/javascript" src="/static/js/jquery-1.10.1.min.js"></script></head><body>${next.body()}</body></html>
修改regist.mako文件:
<%inherit file="/template.mako" /><div class="header pure-g-r"><h1>注册</h1></div><div class="account"><form class="pure-form" method="post"><label>手机</label><input name="phone" id="phone" type="text" placeholder="请输入您的手机号码"> <label>姓名</label><input name="name" id="name" type="text" placeholder="请输入您的姓名"> <label>密码</label><input name="password" id="password" type="password" placeholder="请输入密码"> <a class="pure-button pure-button-primary" id="regist-btn">注册</a><a class="pure-button back-btn pure-button-primary">返回</a></form></div><script>$(document).ready(function(){$('#regist-btn').click(function(){if($('#phone').val()==""){alert('请输入手机号码');}else if($('#password').val()==""){alert('请输入密码');}else if($('#name').val()==""){alert('请输入姓名');}else{$.ajax({url:'/user/regist',type:'POST',dataType:'json',data:{'phone':$('#phone').val(),'password':$('#password').val(),'name':$('#name').val()},success:function(data){if(data.error){if(data.form_errors && data.form_errors.phone)alert(data.form_errors.phone);else if(data.form_errors && data.form_errors.password)alert(data.form_errors.password);else if(data.form_errors && data.form_errors.name)alert('姓名:'+data.form_errors.name);else alert(data.error);}else if(data.result==1){window.location.href="/share/event?id=533bd7c3fbe78e78841aa359";}else{}},error:function(data){console.log('系统错误!');}});}});});</script>
最后运行项目,一个完整地注册流程就ok了。运行前需要先开启MongoDB,并且确定创建了myproject数据库和相应集合。
源代码:
http://pan.baidu.com/s/15ZLBC
- pyramid学习笔记3-创建注册页面
- pyramid学习笔记1-创建pyramid web项目
- pyramid学习笔记0-准备工作
- 安卓学习笔记:2:用EditView创建一个简单的注册页面
- Python Web框架pyramid学习笔记
- pyramid学习笔记x-mongodb基本操作
- 创建注册页面
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- RCNN学习笔记(3):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPP-net)
- Django学习笔记---创建第一个页面
- QML学习笔记 创建页面表示方法
- bootstrap创建登录注册页面
- bootstrap创建登录注册页面
- pyramid学习笔记2-做一个活动组织网站
- wireshark错误包显示和隐藏
- 人与计算机的区别
- NYOJ 891 找点
- 初识spring boot maven管理--配置文件
- 2014_04_14第16周周四工作日志:获取用户sid的三种方法
- pyramid学习笔记3-创建注册页面
- Java学习记录7
- 阿里巴巴2011笔试题+答案解析
- NYOJ 91 阶乘之和
- Java学习记录8
- PAT 1074. Reversing Linked List
- yahoo.com邮箱foxmail收发邮件
- PopupWindow
- RTMP流媒体协议在视频监控系统中应用的优势