├── .idea ├── .name ├── Tyrion.iml ├── dictionaries │ └── wupeiqi.xml ├── encodings.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml ├── vcs.xml └── workspace.xml ├── LICENSE ├── MANIFEST.in ├── PyTyrion.egg-info ├── PKG-INFO ├── SOURCES.txt ├── dependency_links.txt └── top_level.txt ├── README.rst ├── Tyrion ├── Fields.py ├── Forms.py ├── Framework.py ├── Widget.py ├── __init__.py └── __pycache__ │ ├── Fields.cpython-35.pyc │ ├── Forms.cpython-35.pyc │ ├── Framework.cpython-35.pyc │ ├── Widget.cpython-35.pyc │ └── __init__.cpython-35.pyc ├── dist └── PyTyrion-1.0.1.tar.gz └── setup.py /.idea/.name: -------------------------------------------------------------------------------- 1 | Tyrion -------------------------------------------------------------------------------- /.idea/Tyrion.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/dictionaries/wupeiqi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 142 | 143 | 176 | 177 | 178 | true 179 | 180 | 181 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 216 | 217 | 218 | 219 | 222 | 223 | 226 | 227 | 228 | 229 | 232 | 233 | 236 | 237 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 258 | 259 | 260 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 289 | 290 | 309 | 310 | 329 | 330 | 349 | 350 | 369 | 370 | 389 | 390 | 414 | 415 | 436 | 437 | 454 | 455 | 472 | 473 | 474 | 475 | 476 | 498 | 499 | 512 | 513 | 532 | 533 | 534 | 535 | 536 | 537 | true 538 | 539 | 540 | 541 | 542 | 555 | 556 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 1474858214961 597 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 632 | 635 | 636 | 637 | 639 | 640 | 644 | 645 | 646 | 647 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 WuPeiqi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include the readme file 2 | include READEME.rst 3 | -------------------------------------------------------------------------------- /PyTyrion.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.1 2 | Name: PyTyrion 3 | Version: 1.0.1 4 | Summary: 支持Tornado、Django、Bottle、Flask的Web表单验证 5 | Home-page: https://github.com/WuPeiqi/Tyrion 6 | Author: wupeiqi 7 | Author-email: wupeiq@live.com 8 | License: MIT 9 | Description: Python Web框架表单验证组件 - Tyrion 10 | ======================= 11 | 12 | Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado、Django、Flask、Bottle Web框架。 13 | Tyrion主要有两大重要动能: 14 | 15 | - 表单验证 16 | 17 | - 生成HTML标签 18 | 19 | - 保留上次提交内容 20 | 21 | 对于表单验证,告别书写重复的正则表达式对用户提交的数据进行验证的工作,从此解放双手,跟着我左手右手一个慢动作... 22 | 23 | 对于生成HTML标签,不在人工书写html标签,让Tyrion帮你自动创建... 24 | 25 | 对于保留上次提交内容,由于默认表单提交后页面刷新,原来输入的内容会清空,Tyrion可以保留上次提交内容。 26 | 27 | 下载安装 28 | ::::::::: 29 | :: 30 | 31 | pip3 install PyTyrion 32 | 33 | 中文文档 34 | ::::::::: 35 | http://www.cnblogs.com/wupeiqi/p/5938916.html 36 | 37 | Keywords: web form python tornado django bottle flask 38 | Platform: UNKNOWN 39 | Classifier: Development Status :: 4 - Beta 40 | Classifier: Intended Audience :: Developers 41 | Classifier: Topic :: Software Development :: Build Tools 42 | Classifier: License :: OSI Approved :: MIT License 43 | Classifier: Programming Language :: Python :: 2 44 | Classifier: Programming Language :: Python :: 2.6 45 | Classifier: Programming Language :: Python :: 2.7 46 | Classifier: Programming Language :: Python :: 3 47 | Classifier: Programming Language :: Python :: 3.3 48 | Classifier: Programming Language :: Python :: 3.4 49 | Classifier: Programming Language :: Python :: 3.5 50 | -------------------------------------------------------------------------------- /PyTyrion.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | MANIFEST.in 2 | README.rst 3 | setup.py 4 | PyTyrion.egg-info/.DS_Store 5 | PyTyrion.egg-info/PKG-INFO 6 | PyTyrion.egg-info/SOURCES.txt 7 | PyTyrion.egg-info/dependency_links.txt 8 | PyTyrion.egg-info/top_level.txt 9 | Tyrion/Fields.py 10 | Tyrion/Forms.py 11 | Tyrion/Framework.py 12 | Tyrion/Widget.py 13 | Tyrion/__init__.py -------------------------------------------------------------------------------- /PyTyrion.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /PyTyrion.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | Tyrion 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Python Web框架表单验证组件 - Tyrion 2 | ======================= 3 | 4 | Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado、Django、Flask、Bottle Web框架。 5 | Tyrion主要有两大重要动能: 6 | 7 | - 表单验证 8 | 9 | - 生成HTML标签 10 | 11 | - 保留上次提交内容 12 | 13 | 对于表单验证,告别书写重复的正则表达式对用户提交的数据进行验证的工作,从此解放双手,跟着我左手右手一个慢动作... 14 | 15 | 对于生成HTML标签,不在人工书写html标签,让Tyrion帮你自动创建... 16 | 17 | 对于保留上次提交内容,由于默认表单提交后页面刷新,原来输入的内容会清空,Tyrion可以保留上次提交内容。 18 | 19 | 下载安装 20 | ::::::::: 21 | :: 22 | 23 | pip3 install PyTyrion 24 | 25 | 中文文档 26 | ::::::::: 27 | http://www.cnblogs.com/wupeiqi/p/5938916.html 28 | -------------------------------------------------------------------------------- /Tyrion/Fields.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | import re 4 | from Tyrion import Widget 5 | from Tyrion.Framework import FrameworkFactory 6 | 7 | 8 | class Field(object): 9 | """ 10 | 所有Form字段的基类 11 | """ 12 | 13 | def __init__(self, widget): 14 | self.status = False 15 | self.name = None 16 | self.value = None 17 | self.error = None 18 | self.widget = widget 19 | 20 | def valid(self, handler): 21 | """ 22 | 字段必须实现该方法,用于从请求中获取用户输入的值并和规则进行比较 23 | :param handler: Tornado处理请求的XXXHandler对象 24 | :return: 25 | """ 26 | raise NotImplementedError('your class %s must implement valid method' % self.__class__) 27 | 28 | def __str__(self): 29 | 30 | if self.value == None: 31 | return str(self.widget) 32 | 33 | if isinstance(self.widget, Widget.SingleSelect): 34 | self.widget.selected_value = self.value 35 | elif isinstance(self.widget, Widget.MultiSelect): 36 | self.widget.selected_value_list = self.value 37 | elif isinstance(self.widget, Widget.InputSingleCheckBox): 38 | self.widget.attr['checked'] = 'checked' 39 | elif isinstance(self.widget, Widget.InputMultiCheckBox): 40 | self.widget.checked_value_list = self.value 41 | elif isinstance(self.widget, Widget.InputRadio): 42 | self.widget.checked_value = self.value 43 | elif isinstance(self.widget, Widget.TextArea): 44 | self.widget.value = self.value 45 | else: 46 | self.widget.attr['value'] = self.value 47 | return str(self.widget) 48 | 49 | def set_value(self, value): 50 | self.value = value 51 | 52 | 53 | class StringField(Field): 54 | """ 55 | 字符串类字段 56 | """ 57 | REGULAR = "^.*$" 58 | DEFAULT_WIDGET = Widget.InputText 59 | 60 | def __init__(self, max_length=None, min_length=None, error=None, required=True, widget=None): 61 | """ 62 | :param error: 自定义错误信息 63 | 如:{ 64 | 'required': '值为空时的错误提示', 65 | 'invalid': '格式错误时的错误提示', 66 | 'max_length': '最大长度为10', 67 | 'min_length': '最小长度为1', 68 | } 69 | :param required: 是否必须 70 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 71 | :return: 72 | """ 73 | self.custom_error_dict = {} 74 | if error: 75 | self.custom_error_dict.update(error) 76 | 77 | self.required = required 78 | self.max_length = max_length 79 | self.min_length = min_length 80 | 81 | widget = widget if widget else self.DEFAULT_WIDGET() 82 | 83 | super(StringField, self).__init__(widget) 84 | 85 | def valid(self, handler): 86 | """ 87 | 从请求中获取用户输入的值并和规则进行比较 88 | :param handler: Tornado处理请求的XXXHandler对象 89 | :return: 90 | """ 91 | input_value = FrameworkFactory.get_framework().get_argument(handler, self.name, None) 92 | # input_value = handler.get_argument(self.name, None) 93 | 94 | self.value = input_value 95 | 96 | if not input_value: 97 | if not self.required: 98 | self.status = True 99 | return 100 | 101 | if self.custom_error_dict.get('required', None): 102 | self.error = self.custom_error_dict['required'] 103 | else: 104 | self.error = "%s is required" % self.name 105 | return 106 | 107 | ret = re.match(self.REGULAR, input_value) 108 | if not ret: 109 | if self.custom_error_dict.get('invalid', None): 110 | self.error = self.custom_error_dict['invalid'] 111 | else: 112 | self.error = "%s is invalid" % self.name 113 | return 114 | 115 | if self.max_length: 116 | if len(input_value) > self.max_length: 117 | if self.custom_error_dict.get('max_length', None): 118 | self.error = self.custom_error_dict['max_length'] 119 | else: 120 | self.error = "%s max length is %s" % (self.name, self.max_length) 121 | return 122 | 123 | if self.min_length: 124 | 125 | if len(input_value) < self.min_length: 126 | if self.custom_error_dict.get('min_length', None): 127 | self.error = self.custom_error_dict['min_length'] 128 | else: 129 | self.error = "%s min length is %s" % (self.name, self.min_length) 130 | return 131 | 132 | self.status = True 133 | 134 | 135 | class EmailField(Field): 136 | """ 137 | 字符串类字段 138 | """ 139 | REGULAR = "^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$" 140 | DEFAULT_WIDGET = Widget.InputText 141 | 142 | def __init__(self, max_length=None, min_length=None, error=None, required=True, widget=None): 143 | """ 144 | :param error: 自定义错误信息 145 | 如:{ 146 | 'required': '值为空时的错误提示', 147 | 'invalid': '格式错误时的错误提示', 148 | 'max_length': '最大长度为10', 149 | 'min_length': '最小长度为1', 150 | } 151 | :param required: 是否必须 152 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 153 | :return: 154 | """ 155 | self.custom_error_dict = {} 156 | if error: 157 | self.custom_error_dict.update(error) 158 | 159 | self.required = required 160 | self.max_length = max_length 161 | self.min_length = min_length 162 | 163 | widget = widget if widget else self.DEFAULT_WIDGET() 164 | 165 | super(EmailField, self).__init__(widget) 166 | 167 | def valid(self, handler): 168 | """ 169 | 从请求中获取用户输入的值并和规则进行比较 170 | :param handler: Tornado处理请求的XXXHandler对象 171 | :return: 172 | """ 173 | 174 | input_value = FrameworkFactory.get_framework().get_argument(handler, self.name, None) 175 | # input_value = handler.get_argument(self.name, None) 176 | 177 | self.value = input_value 178 | if not input_value: 179 | if not self.required: 180 | self.status = True 181 | return 182 | if self.custom_error_dict.get('required', None): 183 | self.error = self.custom_error_dict['required'] 184 | else: 185 | self.error = "%s is required" % self.name 186 | return 187 | 188 | ret = re.match(self.REGULAR, input_value) 189 | if not ret: 190 | if self.custom_error_dict.get('invalid', None): 191 | self.error = self.custom_error_dict['invalid'] 192 | else: 193 | self.error = "%s is invalid" % self.name 194 | return 195 | 196 | if self.max_length: 197 | if len(input_value) > self.max_length: 198 | if self.custom_error_dict.get('max_length', None): 199 | self.error = self.custom_error_dict['max_length'] 200 | else: 201 | self.error = "%s max length is %s" % (self.name, self.max_length) 202 | return 203 | 204 | if self.min_length: 205 | if len(input_value) < self.max_length: 206 | if self.custom_error_dict.get('min_length', None): 207 | self.error = self.custom_error_dict['min_length'] 208 | else: 209 | self.error = "%s min length is %s" % (self.name, self.min_length) 210 | return 211 | 212 | self.status = True 213 | 214 | 215 | class IPField(Field): 216 | """ 217 | 字符串类字段 218 | """ 219 | REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 220 | DEFAULT_WIDGET = Widget.InputText 221 | 222 | def __init__(self, max_length=None, min_length=None, error=None, required=True, widget=None): 223 | """ 224 | :param error: 自定义错误信息 225 | 如:{ 226 | 'required': '值为空时的错误提示', 227 | 'invalid': '格式错误时的错误提示', 228 | 'max_length': '最大长度为10', 229 | 'min_length': '最小长度为1', 230 | } 231 | :param required: 是否必须 232 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 233 | :return: 234 | """ 235 | self.custom_error_dict = {} 236 | if error: 237 | self.custom_error_dict.update(error) 238 | 239 | self.required = required 240 | self.max_length = max_length 241 | self.min_length = min_length 242 | 243 | widget = widget if widget else self.DEFAULT_WIDGET() 244 | 245 | super(IPField, self).__init__(widget) 246 | 247 | def valid(self, handler): 248 | """ 249 | 从请求中获取用户输入的值并和规则进行比较 250 | :param handler: Tornado处理请求的XXXHandler对象 251 | :return: 252 | """ 253 | input_value = FrameworkFactory.get_framework().get_argument(handler, self.name, None) 254 | # input_value = handler.get_argument(self.name, None) 255 | 256 | self.value = input_value 257 | if not input_value: 258 | if not self.required: 259 | self.status = True 260 | return 261 | 262 | if self.custom_error_dict.get('required', None): 263 | self.error = self.custom_error_dict['required'] 264 | else: 265 | self.error = "%s is required" % self.name 266 | return 267 | 268 | ret = re.match(self.REGULAR, input_value) 269 | if not ret: 270 | if self.custom_error_dict.get('invalid', None): 271 | self.error = self.custom_error_dict['invalid'] 272 | else: 273 | self.error = "%s is invalid" % self.name 274 | return 275 | 276 | if self.max_length: 277 | if len(input_value) > self.max_length: 278 | if self.custom_error_dict.get('max_length', None): 279 | self.error = self.custom_error_dict['max_length'] 280 | else: 281 | self.error = "%s max length is %s" % (self.name, self.max_length) 282 | return 283 | 284 | if self.min_length: 285 | if len(input_value) < self.max_length: 286 | if self.custom_error_dict.get('min_length', None): 287 | self.error = self.custom_error_dict['min_length'] 288 | else: 289 | self.error = "%s min length is %s" % (self.name, self.min_length) 290 | return 291 | 292 | self.status = True 293 | 294 | 295 | class IntegerField(Field): 296 | """ 297 | 字符串类字段 298 | """ 299 | REGULAR = "^\d+$" 300 | DEFAULT_WIDGET = Widget.InputText 301 | 302 | def __init__(self, max_value=None, min_value=None, error=None, required=True, widget=None): 303 | """ 304 | :param error: 自定义错误信息 305 | 如:{ 306 | 'required': '值为空时的错误提示', 307 | 'invalid': '格式错误时的错误提示', 308 | 'max_value': '最大值为10', 309 | 'max_value': '最小值度为1', 310 | } 311 | :param required: 是否必须 312 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 313 | :return: 314 | """ 315 | self.custom_error_dict = {} 316 | if error: 317 | self.custom_error_dict.update(error) 318 | 319 | self.required = required 320 | self.max_value = max_value 321 | self.min_value = min_value 322 | 323 | widget = widget if widget else self.DEFAULT_WIDGET() 324 | 325 | super(IntegerField, self).__init__(widget) 326 | 327 | def valid(self, handler): 328 | """ 329 | 从请求中获取用户输入的值并和规则进行比较 330 | :param handler: Tornado处理请求的XXXHandler对象 331 | :return: 332 | """ 333 | input_value = FrameworkFactory.get_framework().get_argument(handler, self.name, None) 334 | # input_value = handler.get_argument(self.name, None) 335 | 336 | self.value = input_value 337 | 338 | if not input_value: 339 | if not self.required: 340 | self.status = True 341 | return 342 | 343 | if self.custom_error_dict.get('required', None): 344 | self.error = self.custom_error_dict['required'] 345 | else: 346 | self.error = "%s is required" % self.name 347 | return 348 | 349 | ret = re.match(self.REGULAR, input_value) 350 | if not ret: 351 | if self.custom_error_dict.get('invalid', None): 352 | self.error = self.custom_error_dict['invalid'] 353 | else: 354 | self.error = "%s is invalid" % self.name 355 | return 356 | 357 | input_value = int(input_value) 358 | self.value = input_value 359 | 360 | if self.max_value: 361 | if input_value > self.max_value: 362 | if self.custom_error_dict.get('max_value', None): 363 | self.error = self.custom_error_dict['max_value'] 364 | else: 365 | self.error = "%s max value is %s" % (self.name, self.max_value) 366 | return 367 | 368 | if self.min_value: 369 | if input_value < self.min_value: 370 | if self.custom_error_dict.get('min_value', None): 371 | self.error = self.custom_error_dict['min_value'] 372 | else: 373 | self.error = "%s min value is %s" % (self.name, self.min_value) 374 | return 375 | 376 | self.status = True 377 | 378 | 379 | class FloatField(Field): 380 | """ 381 | 字符串类字段 382 | """ 383 | REGULAR = "^\d+(\.\d{1,2})?$" 384 | DEFAULT_WIDGET = Widget.InputText 385 | 386 | def __init__(self, max_value=None, min_value=None, error=None, required=True, widget=None): 387 | """ 388 | :param error: 自定义错误信息 389 | 如:{ 390 | 'required': '值为空时的错误提示', 391 | 'invalid': '格式错误时的错误提示', 392 | 'max_value': '最大值为10', 393 | 'min_value': '最小值度为1', 394 | } 395 | :param required: 是否必须 396 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 397 | :return: 398 | """ 399 | self.custom_error_dict = {} 400 | if error: 401 | self.custom_error_dict.update(error) 402 | 403 | self.required = required 404 | self.max_value = max_value 405 | self.min_value = min_value 406 | 407 | widget = widget if widget else self.DEFAULT_WIDGET() 408 | 409 | super(FloatField, self).__init__(widget) 410 | 411 | def valid(self, handler): 412 | """ 413 | 从请求中获取用户输入的值并和规则进行比较 414 | :param handler: Tornado处理请求的XXXHandler对象 415 | :return: 416 | """ 417 | input_value = FrameworkFactory.get_framework().get_argument(handler, self.name, None) 418 | # input_value = handler.get_argument(self.name, None) 419 | 420 | self.value = input_value 421 | if not input_value: 422 | if not self.required: 423 | self.status = True 424 | return 425 | 426 | if self.custom_error_dict.get('required', None): 427 | self.error = self.custom_error_dict['required'] 428 | else: 429 | self.error = "%s is required" % self.name 430 | return 431 | 432 | ret = re.match(self.REGULAR, input_value) 433 | if not ret: 434 | if self.custom_error_dict.get('invalid', None): 435 | self.error = self.custom_error_dict['invalid'] 436 | else: 437 | self.error = "%s is invalid" % self.name 438 | return 439 | 440 | input_value = float(input_value) 441 | self.value = input_value 442 | 443 | if self.max_value: 444 | if input_value > self.max_value: 445 | if self.custom_error_dict.get('max_value', None): 446 | self.error = self.custom_error_dict['max_value'] 447 | else: 448 | self.error = "%s max value is %s" % (self.name, self.max_value) 449 | return 450 | 451 | if self.min_value: 452 | if input_value < self.min_value: 453 | if self.custom_error_dict.get('min_value', None): 454 | self.error = self.custom_error_dict['min_value'] 455 | else: 456 | self.error = "%s min value is %s" % (self.name, self.min_value) 457 | return 458 | 459 | self.status = True 460 | 461 | 462 | class StringListField(Field): 463 | """ 464 | 字符串类字段 465 | """ 466 | REGULAR = "^.*$" 467 | DEFAULT_WIDGET = Widget.InputMultiCheckBox 468 | 469 | def __init__(self, ele_max_length=None, ele_min_length=None, error=None, required=True, widget=None): 470 | """ 471 | :param error: 自定义错误信息 472 | 如:{ 473 | 'required': '值为空时的错误提示', 474 | 'element': '列表中的元素必须是字符串', 475 | 'ele_max_length': '最大长度为10', 476 | 'ele_min_length': '最小长度为1', 477 | } 478 | :param required: 是否必须 479 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 480 | :return: 481 | """ 482 | self.custom_error_dict = {} 483 | if error: 484 | self.custom_error_dict.update(error) 485 | 486 | self.required = required 487 | self.ele_max_length = ele_max_length 488 | self.ele_min_length = ele_min_length 489 | 490 | widget = widget if widget else self.DEFAULT_WIDGET() 491 | 492 | super(StringListField, self).__init__(widget) 493 | 494 | def valid(self, handler): 495 | """ 496 | 从请求中获取用户输入的值并和规则进行比较 497 | :param handler: Tornado处理请求的XXXHandler对象 498 | :return: 499 | """ 500 | input_value = FrameworkFactory.get_framework().get_arguments(handler, self.name, []) 501 | # input_value = handler.get_arguments(self.name) 502 | 503 | self.value = input_value 504 | 505 | if not input_value: 506 | if not self.required: 507 | self.status = True 508 | return 509 | 510 | if self.custom_error_dict.get('required', None): 511 | self.error = self.custom_error_dict['required'] 512 | else: 513 | self.error = "%s is required" % self.name 514 | return 515 | 516 | for value in input_value: 517 | ret = re.match(self.REGULAR, value) 518 | if not ret: 519 | if self.custom_error_dict.get('element', None): 520 | self.error = self.custom_error_dict['element'] 521 | else: 522 | self.error = "element %s is invalid" % self.name 523 | return 524 | 525 | if self.ele_max_length: 526 | if len(value) > self.ele_max_length: 527 | if self.custom_error_dict.get('ele_max_length', None): 528 | self.error = self.custom_error_dict['ele_max_length'] 529 | else: 530 | self.error = "element %s max length is %s" % (self.name, self.ele_max_length) 531 | return 532 | 533 | if self.ele_min_length: 534 | 535 | if len(value) < self.ele_min_length: 536 | if self.custom_error_dict.get('ele_min_length', None): 537 | self.error = self.custom_error_dict['ele_min_length'] 538 | else: 539 | self.error = "element %s min length is %s" % (self.name, self.ele_min_length) 540 | return 541 | 542 | self.status = True 543 | 544 | 545 | class IntegerListField(Field): 546 | """ 547 | 字符串类字段 548 | """ 549 | REGULAR = "^\d+$" 550 | DEFAULT_WIDGET = Widget.InputMultiCheckBox 551 | 552 | def __init__(self, ele_max_value=None, ele_min_value=None, error=None, required=True, widget=None): 553 | """ 554 | :param error: 自定义错误信息 555 | 如:{ 556 | 'required': '值为空时的错误提示', 557 | 'element': '列表中的元素必须是数字', 558 | 'ele_max_value': '最大值为x', 559 | 'ele_min_value': '最小值为x', 560 | } 561 | :param required: 是否必须 562 | :param widget: 指定插件,用于生成HTML标签(默认生成Input标签) 563 | :return: 564 | """ 565 | self.custom_error_dict = {} 566 | if error: 567 | self.custom_error_dict.update(error) 568 | 569 | self.required = required 570 | self.ele_max_value = ele_max_value 571 | self.ele_min_value = ele_min_value 572 | 573 | widget = widget if widget else self.DEFAULT_WIDGET() 574 | 575 | super(IntegerListField, self).__init__(widget) 576 | 577 | def valid(self, handler): 578 | """ 579 | 从请求中获取用户输入的值并和规则进行比较 580 | :param handler: Tornado处理请求的XXXHandler对象 581 | :return: 582 | """ 583 | input_value = FrameworkFactory.get_framework().get_arguments(handler, self.name, []) 584 | # input_value = handler.get_arguments(self.name) 585 | self.value = input_value 586 | 587 | if not input_value: 588 | if not self.required: 589 | self.status = True 590 | return 591 | 592 | if self.custom_error_dict.get('required', None): 593 | self.error = self.custom_error_dict['required'] 594 | else: 595 | self.error = "%s is required" % self.name 596 | return 597 | 598 | success_value_list = [] 599 | for value in input_value: 600 | ret = re.match(self.REGULAR, value) 601 | if not ret: 602 | if self.custom_error_dict.get('element', None): 603 | self.error = self.custom_error_dict['element'] 604 | else: 605 | self.error = "element %s is invalid" % self.name 606 | return 607 | value = int(value) 608 | success_value_list.append(value) 609 | 610 | if self.ele_max_value: 611 | if value > self.ele_max_value: 612 | if self.custom_error_dict.get('ele_max_value', None): 613 | self.error = self.custom_error_dict['ele_max_value'] 614 | else: 615 | self.error = "element %s max value is %s" % (self.name, self.ele_max_value) 616 | return 617 | 618 | if self.ele_min_value: 619 | 620 | if value < self.ele_min_value: 621 | if self.custom_error_dict.get('ele_min_value', None): 622 | self.error = self.custom_error_dict['ele_min_value'] 623 | else: 624 | self.error = "element %s min value is %s" % (self.name, self.ele_min_value) 625 | return 626 | 627 | self.value = success_value_list 628 | self.status = True -------------------------------------------------------------------------------- /Tyrion/Forms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | import copy 4 | from Tyrion.Fields import Field 5 | 6 | 7 | class Form(object): 8 | def __init__(self, handler=None): 9 | """ 10 | 11 | :param handler: Tornado请求中的XXXHandler对象 12 | :return: 13 | """ 14 | self.handler = handler 15 | self.FiledDict = {} 16 | self.value_dict = {} 17 | self.error_dict = {} 18 | self.valid_status = True 19 | 20 | self.initialize() 21 | 22 | def initialize(self): 23 | """ 24 | 初始化,将派生类Form中的静态字段拷贝到字段FiledDict中,并为字段对应的Html插件设置id和name属性 25 | :return: 26 | """ 27 | for k, v in self.__class__.__dict__.items(): 28 | if isinstance(v, Field): 29 | field = copy.deepcopy(v) 30 | field.name = k 31 | field.widget.attr['name'] = k 32 | """ 33 | if 'id' not in field.widget.attr: 34 | field.widget.attr['id'] = '%s_%s' % ('id', k) 35 | """ 36 | self.FiledDict[k] = field 37 | self.__dict__.update(self.FiledDict) 38 | 39 | def is_valid(self): 40 | """ 41 | 验证用户输入和规则是否匹配 42 | :return: 43 | """ 44 | for k, v in self.FiledDict.items(): 45 | v.valid(self.handler) 46 | if v.status: 47 | self.value_dict[k] = v.value 48 | else: 49 | self.error_dict[k] = v.error 50 | self.valid_status = False 51 | 52 | return self.valid_status 53 | 54 | def init_field_value(self, value_dict): 55 | """ 56 | 设置默认 显示的值 或 选中的值 57 | :param value_dict: 58 | :return: 59 | """ 60 | for k, v in self.FiledDict.items(): 61 | v.set_value(value_dict.get(k, None)) 62 | 63 | -------------------------------------------------------------------------------- /Tyrion/Framework.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | 4 | 5 | class FrameworkFactory(object): 6 | __framework = None 7 | 8 | @staticmethod 9 | def set_framework(framework): 10 | FrameworkFactory.__framework = framework 11 | 12 | @staticmethod 13 | def get_framework(): 14 | return FrameworkFactory.__framework 15 | 16 | 17 | class BaseFramework(object): 18 | def get_argument(self, request, name, default=None): 19 | raise NotImplementedError('class %s must implement get_argument method' % self.__class__) 20 | 21 | def get_arguments(self, request, name, default=None): 22 | raise NotImplementedError('class %s must implement get_arguments method' % self.__class__) 23 | 24 | 25 | class Tornado(BaseFramework): 26 | def get_argument(self, request, name, default=None): 27 | """ 28 | 从请求中获取用户输入或选择的单值 29 | PS: 30 | request.get_argument('username',None) 表示从GET和POST等中获取请求 31 | request.get_query_argument('username',None) 表示从GET中获取请求 32 | request.get_body_argument('username',None) 表示从POST等中获取请求 33 | :param request: Tornado请求中的的 xxxHandler对象,即:self;如:self.get_argument('username',None) 34 | :param name: 35 | :param default: 36 | :return: 37 | """ 38 | return request.get_argument(name, default) 39 | 40 | def get_arguments(self, request, name, default=None): 41 | """ 42 | 从请求中获取用户输入或选择的多个值(列表类型) 43 | PS: 44 | request.get_argument('username',None) 表示从GET和POST等中获取请求 45 | request.get_query_argument('username',None) 表示从GET中获取请求 46 | request.get_body_argument('username',None) 表示从POST等中获取请求 47 | :param request: Tornado请求中的的 xxxHandler对象,即:self;如:self.get_argument('username',None) 48 | :param name: 49 | :param default: 50 | :return: 51 | """ 52 | value = request.get_arguments(name) 53 | if value: 54 | return value 55 | return default 56 | 57 | 58 | class Django(BaseFramework): 59 | def get_argument(self, request, name, default=None): 60 | """ 61 | :param request: Django中request参数 62 | :param name: 63 | :param default: 64 | :return: 65 | """ 66 | post = request.POST.get(name) 67 | if post: 68 | return post 69 | get = request.GET.get(name) 70 | if get: 71 | return get 72 | return default 73 | 74 | def get_arguments(self, request, name, default=None): 75 | """ 76 | 77 | :param request: 78 | :param name: 79 | :param default: 80 | :return: 81 | """ 82 | post = request.POST.getlist(name) 83 | if post: 84 | return post 85 | get = request.GET.getlist(name) 86 | if get: 87 | return get 88 | return default 89 | 90 | 91 | class Flask(BaseFramework): 92 | def get_argument(self, request, name, default=None): 93 | """ 94 | 从请求中获取用户输入或选择的单值 95 | PS: 96 | request.values 表示从GET和POST中获取请求 97 | request.form 表示从POST中获取请求 98 | request.arg 表示从GET中获取请求 99 | :param request: Flask框架中封装了用户请求的request,即:from flask import request 100 | :param name: 101 | :param default: 102 | :return: 103 | """ 104 | return request.values.get(name, default) 105 | 106 | def get_arguments(self, request, name, default=None): 107 | """ 108 | 从请求中获取用户输入或选择的多个值 109 | PS: 110 | request.values 表示从GET和POST中获取请求 111 | request.form 表示从POST中获取请求 112 | request.arg 表示从GET中获取请求 113 | :param request: Flask框架中封装了用户请求的request,即:from flask import request 114 | :param name: 115 | :param default: 116 | :return: 117 | """ 118 | get_post = request.values.getlist(name) 119 | if get_post: 120 | return get_post 121 | return default 122 | 123 | 124 | class Bottle(BaseFramework): 125 | def get_argument(self, request, name, default=None): 126 | """ 127 | 从请求中获取用户输入或选择的单值 128 | PS: 129 | request.params 表示从GET和POST中获取请求 130 | request.forms 表示从POST中获取请求 131 | request.query 表示从GET中获取请求 132 | :param request: Bottle框架中封装了用户请求的request,即:from bottle import request 133 | :param name: 134 | :param default: 135 | :return: 136 | """ 137 | get_post = request.params.get(name, default) 138 | return get_post 139 | 140 | def get_arguments(self, request, name, default=None): 141 | """ 142 | 从请求中获取用户输入或选择的多个值 143 | PS: 144 | request.params 表示从GET和POST中获取请求 145 | request.forms 表示从POST中获取请求 146 | request.query 表示从GET中获取请求 147 | :param request: Bottle框架中封装了用户请求的request,即:from bottle import request 148 | :param name: 149 | :param default: 150 | :return: 151 | """ 152 | get_post = request.params.getall(name) 153 | if not get_post: 154 | return default 155 | return get_post 156 | -------------------------------------------------------------------------------- /Tyrion/Widget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | 4 | 5 | class Input(object): 6 | def __init__(self, attr=None): 7 | """ 8 | :param attr: 生成的HTML属性,如:{'id': '123'} 9 | :return: 10 | """ 11 | self.attr = attr if attr else {} 12 | 13 | def __str__(self): 14 | """ 15 | 使用对象时返回的字符串 16 | :return: 17 | """ 18 | t = "" 19 | attr_list = [] 20 | for k, v in self.attr.items(): 21 | temp = "%s='%s' " % (k, v,) 22 | attr_list.append(temp) 23 | tag = t % (''.join(attr_list)) 24 | return tag 25 | 26 | 27 | class InputText(Input): 28 | def __init__(self, attr=None): 29 | attr_dict = {'type': 'text'} 30 | if attr: 31 | attr_dict.update(attr) 32 | super(InputText, self).__init__(attr_dict) 33 | 34 | 35 | class InputEmail(Input): 36 | def __init__(self, attr=None): 37 | attr_dict = {'type': 'email'} 38 | if attr: 39 | attr_dict.update(attr) 40 | super(InputEmail, self).__init__(attr_dict) 41 | 42 | 43 | class InputPassword(Input): 44 | def __init__(self, attr=None): 45 | attr_dict = {'type': 'password'} 46 | if attr: 47 | attr_dict.update(attr) 48 | super(InputPassword, self).__init__(attr_dict) 49 | 50 | 51 | class InputSingleCheckBox(Input): 52 | def __init__(self, attr=None): 53 | attr_dict = {'type': 'checkbox'} 54 | if attr: 55 | attr_dict.update(attr) 56 | super(InputSingleCheckBox, self).__init__(attr_dict) 57 | 58 | def __str__(self): 59 | """ 60 | 使用对象时返回的字符串 61 | :return: 62 | """ 63 | t = "" 64 | attr_list = [] 65 | for k, v in self.attr.items(): 66 | temp = "%s='%s' " % (k, v,) 67 | attr_list.append(temp) 68 | tag = t % (''.join(attr_list)) 69 | return tag 70 | 71 | 72 | class InputMultiCheckBox(object): 73 | def __init__(self, attr=None, text_value_list=None, checked_value_list=None): 74 | """ 75 | :param attr: 生成的HTML属性,如:{'id': '123'} 76 | :param text_value_list: 生成CheckBox的value和内容,如: 77 | [ 78 | {'value':1, 'text': '篮球'}, 79 | {'value':2, 'text': '足球'}, 80 | {'value':3, 'text': '乒乓球'}, 81 | {'value':4, 'text': '羽毛球'}, 82 | ] 83 | :param checked_value_list: 被选中的checked_value_list,如:[2,3] 84 | :return: 85 | """ 86 | attr_dict = {'type': 'checkbox'} 87 | if attr: 88 | attr_dict.update(attr) 89 | self.attr = attr_dict 90 | 91 | self.text_value_list = text_value_list if text_value_list else [] 92 | self.checked_value_list = checked_value_list if checked_value_list else [] 93 | 94 | def __str__(self): 95 | """ 96 | 使用对象时返回的字符串 97 | :return: 98 | """ 99 | tag_list = [] 100 | for item in self.text_value_list: 101 | a = "
%s%s
" 102 | b = "" 103 | attr_list = [] 104 | for k, v in self.attr.items(): 105 | temp = "%s='%s' " % (k, v,) 106 | attr_list.append(temp) 107 | attr_list.append("%s='%s' " % ('value', item['value'])) 108 | if item['value'] in self.checked_value_list: 109 | attr_list.append("checked='checked' ") 110 | input_tag = b % (''.join(attr_list)) 111 | c = a % (input_tag, item['text'], ) 112 | tag_list.append(c) 113 | return ''.join(tag_list) 114 | 115 | 116 | class InputRadio(object): 117 | def __init__(self, attr=None, text_value_list=None, checked_value=None): 118 | """ 119 | :param attr: 生成的HTML属性,如:{'id': '123'} 120 | :param text_value_list: 生成radio的value和内容,如: 121 | [ 122 | {'value':1, 'text': '篮球'}, 123 | {'value':2, 'text': '足球'}, 124 | {'value':3, 'text': '乒乓球'}, 125 | {'value':4, 'text': '羽毛球'}, 126 | ] 127 | :param checked_value: 被选中的checked_value,如:2 128 | :return: 129 | """ 130 | attr_dict = {'type': 'radio'} 131 | if attr: 132 | attr_dict.update(attr) 133 | self.attr = attr_dict 134 | 135 | self.text_value_list = text_value_list if text_value_list else [] 136 | self.checked_value = checked_value 137 | 138 | def __str__(self): 139 | """ 140 | 使用对象时返回的字符串 141 | :return: 142 | """ 143 | tag_list = [] 144 | for item in self.text_value_list: 145 | a = "
%s%s
" 146 | b = "" 147 | attr_list = [] 148 | for k, v in self.attr.items(): 149 | temp = "%s='%s' " % (k, v,) 150 | attr_list.append(temp) 151 | attr_list.append("%s='%s' " % ('value', item['value'])) 152 | if item['value'] == self.checked_value: 153 | attr_list.append("checked='checked' ") 154 | input_tag = b % (''.join(attr_list)) 155 | c = a % (input_tag,item['text']) 156 | tag_list.append(c) 157 | return ''.join(tag_list) 158 | 159 | 160 | class SingleSelect(object): 161 | def __init__(self, attr=None, text_value_list=None, selected_value=None): 162 | """ 163 | :param attr: 生成的HTML属性,如:{'id': '123'} 164 | :param text_value_list: 生成select的value和内容,如: 165 | [ 166 | {'value':1, 'text': '篮球'}, 167 | {'value':2, 'text': '足球'}, 168 | {'value':3, 'text': '乒乓球'}, 169 | {'value':4, 'text': '羽毛球'}, 170 | ] 171 | :param selected_value: 被选中的checked_value,如:2 172 | :return: 173 | """ 174 | attr_dict = {} 175 | if attr: 176 | attr_dict.update(attr) 177 | self.attr = attr_dict 178 | 179 | self.text_value_list = text_value_list if text_value_list else [] 180 | self.selected_value = selected_value 181 | 182 | def __str__(self): 183 | """ 184 | 使用对象时返回的字符串 185 | :return: 186 | """ 187 | 188 | a = "" 189 | 190 | attr_list = [] 191 | for k, v in self.attr.items(): 192 | temp = "%s='%s' " % (k, v,) 193 | attr_list.append(temp) 194 | 195 | option_list = [] 196 | 197 | for item in self.text_value_list: 198 | 199 | if item['value'] == self.selected_value: 200 | b = "" 201 | else: 202 | b = "" 203 | option = b % (item['value'], item['text'],) 204 | option_list.append(option) 205 | 206 | tag = a % (''.join(attr_list), ''.join(option_list)) 207 | 208 | return tag 209 | 210 | 211 | class MultiSelect(object): 212 | def __init__(self, attr=None, text_value_list=None, selected_value_list=None): 213 | """ 214 | :param attr: 生成的Select标签的属性,如:{'id': '123'} 215 | :param text_value_list: 生成CheckBox的value和内容,如: 216 | [ 217 | {'value':1, 'text': '篮球'}, 218 | {'value':2, 'text': '足球'}, 219 | {'value':3, 'text': '乒乓球'}, 220 | {'value':4, 'text': '羽毛球'}, 221 | ] 222 | :param selected_value_list: selected_value_list,如:[2,3,4] 223 | :return: 224 | """ 225 | attr_dict = {'multiple': 'multiple'} 226 | if attr: 227 | attr_dict.update(attr) 228 | self.attr = attr_dict 229 | 230 | self.text_value_list = text_value_list if text_value_list else [] 231 | self.selected_value_list = selected_value_list if selected_value_list else [] 232 | 233 | def __str__(self): 234 | """ 235 | 使用对象时返回的字符串 236 | :return: 237 | """ 238 | 239 | a = "" 240 | 241 | attr_list = [] 242 | for k, v in self.attr.items(): 243 | temp = "%s='%s' " % (k, v,) 244 | attr_list.append(temp) 245 | 246 | option_list = [] 247 | for item in self.text_value_list: 248 | if item['value'] in self.selected_value_list: 249 | b = "" 250 | else: 251 | b = "" 252 | option = b % (item['value'], item['text'],) 253 | option_list.append(option) 254 | 255 | tag = a % (''.join(attr_list), ''.join(option_list)) 256 | return tag 257 | 258 | 259 | class TextArea(object): 260 | def __init__(self, attr=None, value=""): 261 | """ 262 | :param attr: 生成的HTML属性,如:{'id': '123'} 263 | :return: 264 | """ 265 | self.attr = attr if attr else {} 266 | self.value = value 267 | 268 | def __str__(self): 269 | """ 270 | 使用对象时返回的字符串 271 | :return: 272 | """ 273 | t = "" 274 | attr_list = [] 275 | for k, v in self.attr.items(): 276 | temp = "%s='%s' " % (k, v,) 277 | attr_list.append(temp) 278 | tag = t % (''.join(attr_list), self.value) 279 | return tag 280 | 281 | -------------------------------------------------------------------------------- /Tyrion/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | from Tyrion.Framework import FrameworkFactory 4 | from Tyrion.Framework import Tornado 5 | from Tyrion.Framework import Django 6 | from Tyrion.Framework import Bottle 7 | from Tyrion.Framework import Flask 8 | 9 | 10 | __version__ = '1.0.1' 11 | 12 | def setup(framework='tornado'): 13 | """ 14 | 设置Tyrion插件当前处理的Web框架 15 | :param framework: Web框架的字符串表示 16 | :return: 17 | """ 18 | framework_dict = { 19 | 'tornado': Tornado, 20 | 'django': Django, 21 | 'bottle': Bottle, 22 | 'flask': Flask 23 | } 24 | cls = framework_dict.get(framework) 25 | if cls: 26 | FrameworkFactory.set_framework(cls()) 27 | else: 28 | raise Exception('Tyrion模块setup方法参数必须为:%s (任意一种字符串)' % ','.join(framework_dict.keys())) 29 | 30 | 31 | """ 32 | 使用方法:导入模块并且设置使得其支持不同的Web框架 33 | 34 | 如: 35 | import Tyrion 36 | Tyrion.setup('tornado') 37 | 38 | """ 39 | 40 | -------------------------------------------------------------------------------- /Tyrion/__pycache__/Fields.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/Tyrion/__pycache__/Fields.cpython-35.pyc -------------------------------------------------------------------------------- /Tyrion/__pycache__/Forms.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/Tyrion/__pycache__/Forms.cpython-35.pyc -------------------------------------------------------------------------------- /Tyrion/__pycache__/Framework.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/Tyrion/__pycache__/Framework.cpython-35.pyc -------------------------------------------------------------------------------- /Tyrion/__pycache__/Widget.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/Tyrion/__pycache__/Widget.cpython-35.pyc -------------------------------------------------------------------------------- /Tyrion/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/Tyrion/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /dist/PyTyrion-1.0.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuPeiqi/Tyrion/0fec264c975d40a2fa8412c29d63fd48cd5df49b/dist/PyTyrion-1.0.1.tar.gz -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | """A setuptools based setup module. 4 | 5 | See: 6 | https://packaging.python.org/en/latest/distributing.html 7 | https://github.com/pypa/sampleproject 8 | """ 9 | 10 | # Always prefer setuptools over distutils 11 | from setuptools import setup, find_packages 12 | # To use a consistent encoding 13 | from codecs import open 14 | from os import path 15 | import re 16 | 17 | here = path.abspath(path.dirname(__file__)) 18 | 19 | # Get the long description from the README file 20 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f: 21 | long_description = f.read() 22 | 23 | 24 | def read(*parts): 25 | # intentionally *not* adding an encoding option to open, See: 26 | # https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690 27 | return open(path.join(here, *parts), mode='r',encoding='utf-8').read() 28 | 29 | 30 | def find_version(*file_paths): 31 | version_file = read(*file_paths) 32 | version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", 33 | version_file, re.M) 34 | if version_match: 35 | return version_match.group(1) 36 | raise RuntimeError("Unable to find version string.") 37 | 38 | 39 | setup( 40 | name='PyTyrion', 41 | 42 | # Versions should comply with PEP440. For a discussion on single-sourcing 43 | # the version across setup.py and the project code, see 44 | # https://packaging.python.org/en/latest/single_source_version.html 45 | version=find_version("Tyrion", "__init__.py"), 46 | 47 | description='支持Tornado、Django、Bottle、Flask的Web表单验证', 48 | long_description=long_description, 49 | 50 | # The project's main homepage. 51 | url='https://github.com/WuPeiqi/Tyrion', 52 | 53 | # Author details 54 | author='wupeiqi', 55 | author_email='wupeiq@live.com', 56 | 57 | # Choose your license 58 | license='MIT', 59 | 60 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 61 | classifiers=[ 62 | # How mature is this project? Common values are 63 | # 3 - Alpha 64 | # 4 - Beta 65 | # 5 - Production/Stable 66 | 'Development Status :: 4 - Beta', 67 | 68 | # Indicate who your project is intended for 69 | 'Intended Audience :: Developers', 70 | 'Topic :: Software Development :: Build Tools', 71 | 72 | # Pick your license as you wish (should match "license" above) 73 | 'License :: OSI Approved :: MIT License', 74 | 75 | # Specify the Python versions you support here. In particular, ensure 76 | # that you indicate whether you support Python 2, Python 3 or both. 77 | 'Programming Language :: Python :: 2', 78 | 'Programming Language :: Python :: 2.6', 79 | 'Programming Language :: Python :: 2.7', 80 | 'Programming Language :: Python :: 3', 81 | 'Programming Language :: Python :: 3.3', 82 | 'Programming Language :: Python :: 3.4', 83 | 'Programming Language :: Python :: 3.5', 84 | ], 85 | 86 | keywords='web form python tornado django bottle flask', 87 | 88 | packages=find_packages(), 89 | 90 | ) 91 | --------------------------------------------------------------------------------