HTML Forms Data Validation,Transformation&Transformation

formv的Python项目详细描述


formv是一个可配置的python库,可用于验证, 转换HTML表单数据。

在Python2.7和3.2下测试。

包括验证程序:

- basic types
    boolean, strings, numbers, dates, time, ranges, lists, sets
- chained types
    pairs, multiple fields, post-codes, states, currencies,
    languages, phone numbers, credit cards
- compound types
    any validator, piped validators
- signers & encoders
    cost-based PBKDF2 encoding used to sign strings (e.g. cookies),
    encode strings (e.g. user, password) and sign serialized objects
    (e.g. serialized sessions stored on disk)
- documents (.pdf, .txt, .csv, .doc, etc.)
    can be validated (size, mime-type), stored, backed-up, compressed, reused
- images (.jpg, .png, .gif, etc.)
    can be validated (size, mime-type), stored, backed-up, resized, watermarked,
    imprinted, reused
- geographic data
    based on extendable YAML configuration files or user-defined callables:
    countries, country-codes, states, various naming styles, currencies,
    languages, post-codes, latitude, longitude, geo-distance calculation
- network related
    IPv4, IPv6, CIDR, MAC
- web-forms (schema validation)
    simple fields, chained fields, key-based dependency

示例:

#------------------------------------------------------------------------
# schema validation including file upload, transformation and recovery
#------------------------------------------------------------------------

import os, formv
from formv.configuration import build
from formv.validators import *
from formv.exception import Invalid

from formv.utils import dict_object
from formv.utils.compat import PY2
from formv.utils.fileinfo import BaseFileInfo, ReusedFileInfo

from tests import multipart
from examples import to_str, setup_mime_types, make_environ as env

from datetime import datetime
from mimetypes import guess_type
from webob import Request, Response

app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# ----------------------------------------------------------------
# configuration is required only if you use validators based on
# geographic data: countries, currencies, languages, post-codes,
# latitude, longitude, geo-distance calculation,...

formv.config = build(config_root=os.path.join(app_root, 'tests'))

# ----------------------------------------------------------------

mime_types = setup_mime_types()

session = dict_object(files=dict_object())

class WebForm(VSchema):
    fields = {
        'first_name': VString(min_len=3, max_len=50),
        'last_name': VString(min_len=3, max_len=50),
        'postcode': VString(),
        'state': VString(),
        'country': VCountry(required=True, mode='by-name'),
        'email': VEmail(required=True),
        'password': VPassword(special_chars=3),
        'file_upload': VPipe(VUploadFile(mime_types=mime_types,
                                         temp_dir='/tmp/formv/test/tmp',),
                             VWatermarkImage(type='image',
                                             file=os.path.join(app_root, 'tests/watermarks/copyright.jpg'),
                                             opacity=.04, angle=45),
                             VWatermarkImage(text='formv text watermark', angle=25,
                                             color=(0,0,0,128), opacity=1),
                             VImprintImage(text='Note the image watermark in the background',
                                           color=(0,128,128,255)),
                             VImprintImage(text=datetime.strftime(datetime.utcnow(),
                                                                  'Uploaded on %Y/%m/%d - %H:%M:%S GMT'),
                                           color=(255,128,128,255),
                                           margin=(25,10)),
                       )
    }

    chains = {
        'coordinates': VCountryPostcode(country_field='country',     # extracts (latitude, longitude) pair
                                        postcode_field='postcode'),
        'password': VEncodedPair(required_field='password',          # encodes (password, email) pair
                                 required_label='Password',
                                 available_field='email'),
        'state': VState(country_field='country',                     # validates state against country
                        state_field='state', mode='by-name'),
    }

class Application(object):
    def __call__(self, environ, start_response):
        self.request = Request(make_environ())
        response = self.request.get_response(self.response())
        return response(self.request.environ, start_response)

    def response(self):
        try:
            form = self.validate(self.request.POST) # - form validation
            body = to_str(form)
        except Invalid as e:
            # - recover successfully uploaded files
            if isinstance(e.value.get('file_upload'), BaseFileInfo):
                session.files['file_upload'] = ReusedFileInfo(e.value['file_upload'])

            body = e.message
            body += '<br/>errors'
            body += to_str(e.errors)
            body += '<br/>values'
            body += to_str(e.value)

        response = Response()
        response.text = unicode(body) if PY2 else body
        return response

    def validate(self, request):
        form = WebForm(allow_missing_keys=True,
                       allow_extra_keys=True,
                       replace_empty_value=True,
                       empty_values={
                           # inject recovered file back into form if no new file has been uploaded
                           'file_upload': session.files.get('file_upload'),
                       })
        return form.validate(request)

application = Application()

def make_environ():
    ''' simulates a POST request (multipart/form-data) '''

    app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    test_files_dir = os.path.join(app_root, 'tests/files')
    form = []

    # - plain fields
    form.append(multipart.field('first_name', 'John'))
    form.append(multipart.field('last_name', 'Smith'))
    form.append(multipart.field('email', 'dummy@dummy.com'))
    form.append(multipart.field('postcode', '99501'))
    form.append(multipart.field('state', 'Alaska'))
    form.append(multipart.field('country', 'U.S.A.'))
    form.append(multipart.field('password', 'dummy-secret-password-1'))

    # - file upload
    f = os.path.join(test_files_dir, 'test.jpg')
    form.append(multipart.file('file_upload', filename=f,
                               content_type=guess_type(f, False)[0]))
    return env(*form)


if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    httpd = make_server('127.0.0.1', 9000, application)
    sn = httpd.socket.getsockname()
    print("Serving HTTP on", sn[0], "port", sn[1], "...")
    httpd.serve_forever()

输出:

+----------------------------------------------------------------------------------------------------------+
| Field Name  | Field Value                                                                                |
+==========================================================================================================+
| coordinates | (61.216799, -149.87828)                                                                    |
+----------------------------------------------------------------------------------------------------------+
| country     | 'USA'                                                                                      |
+----------------------------------------------------------------------------------------------------------+
| email       | 'dummy@dummy.com'                                                                          |
+----------------------------------------------------------------------------------------------------------+
| file_upload | dir_path = '/tmp/formv/test/public'                                                        |
|             | file_date = datetime.datetime(2014, 4, 4, 1, 33, 39, 453000)                               |
|             | file_ext ='.jpg'                                                                           |
|             | file_name = '16c2493562644b15b4093a02973097b1.jpg'                                         |
|             | file_object = None                                                                         |
|             | file_path = '/tmp/formv/test/public/16c2493562644b15b4093a02973097b1.jpg'                  |
|             | file_size = 5129                                                                           |
|             | guid_name ='16c2493562644b15b4093a02973097b1'                                              |
|             | html_field = 'file_upload'                                                                 |
|             | mime_type = 'image/pjpeg'                                                                  |
|             | orig_name = 'test.jpg'                                                                     |
|             | thumb_name = '16c2493562644b15b4093a02973097b1_th.jpg'                                     |
|             | thumb_path = '/tmp/formv/test/public/16c2493562644b15b4093a02973097b1_th.jpg'              |
|             | zip_name = None                                                                            |
|             | zip_path = None                                                                            |
|             | zip_size = None                                                                            |
+----------------------------------------------------------------------------------------------------------+
| first_name  | 'John'                                                                                     |
+----------------------------------------------------------------------------------------------------------+
| last_name   | 'Smith'                                                                                    |
+----------------------------------------------------------------------------------------------------------+
| password    | '$x-pbkdf2$20$1000$rmQEpiAjI7/FaNpFECFb2w==$l5AfchT7rWwPVxofHhhpSZPu4SJPiU4QTtD/cqmE6og='  |
+----------------------------------------------------------------------------------------------------------+
| postcode    | '99501'                                                                                    |
+----------------------------------------------------------------------------------------------------------+
| state       | 'AK'                                                                                       |
+----------------------------------------------------------------------------------------------------------+

地理配置:

As of now the configuration available includes only USA. If you have to
validates other countries, you have build similar configuration files and
place them in the corresponding folders.

邮政编码验证警告:

If you plan to do USA postcodes validation based on the included YAML
file, expect a high memory usage as the file contains ~44000 postcodes.
A better alternative would be to dump the file in a database, build
necessary callables to read the data and instruct formv to use these
callables. See formv/configuration.py for an example.

美国邮政编码数据源:

http://www.boutell.com/zipcodes/
http://www.boutell.com/zipcodes/zipcode.zip

来源:

https://pypi.python.org/pypi/formv

有关用法和更多示例,请参见示例和测试。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Android:在ListView上使用setOnItemClickListener   使用Netbeans 7.0连接到SQL Server的java正在挂起   java Spring3依赖项注入不适用于mule   java Flink SQL结果字段与LocalDateTime上请求的类型错误不匹配   java找不到文件的结尾   考虑到NamingStrategy,java有没有办法将字符串转换为JsonNode?   使用Netbeans/ant部署java(命令行)应用程序   java如何修复Spring引导多部分上载中的“所需请求部分不存在”   java在应用程序启动时通过引用获取映射未知目标实体属性异常   java形状旋转问题Java2d   Weblogic服务器上的java ExecuteAndWaitInterceptor问题   JavaSpringBoot:project将图像保存在错误的路径中,并且在使用IDEIntellji打开时不显示图像   类向java接口添加方法   Swing组件上的Java 7泛型   sql server如何从java获取用户名。sql。联系   java如何检查该行是否与正则表达式(regex)冲突?   java如何在spring引导安全中为计数失败登录设置验证登录为false   图像如何在Java中使PNG的白色透明?