Home | Trees | Indices | Help |
---|
|
1 # -*- coding: utf-8 -*- 2 # 3 # Copyright (c) 2008-2009 Benoit Chesneau <benoitc@e-engura.com> 4 # 5 # Permission to use, copy, modify, and distribute this software for any 6 # purpose with or without fee is hereby granted, provided that the above 7 # copyright notice and this permission notice appear in all copies. 8 # 9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 # 17 # code heavily inspired from django.forms.models 18 # Copyright (c) Django Software Foundation and individual contributors. 19 # All rights reserved. 20 # 21 # Redistribution and use in source and binary forms, with or without modification, 22 # are permitted provided that the following conditions are met: 23 # 24 # 1. Redistributions of source code must retain the above copyright notice, 25 # this list of conditions and the following disclaimer. 26 # 27 # 2. Redistributions in binary form must reproduce the above copyright 28 # notice, this list of conditions and the following disclaimer in the 29 # documentation and/or other materials provided with the distribution. 30 # 31 # 3. Neither the name of Django nor the names of its contributors may be used 32 # to endorse or promote products derived from this software without 33 # specific prior written permission. 34 # 35 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 36 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 37 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 39 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 41 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 42 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 43 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 44 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 46 """ Implement DocumentForm object. It map Document objects to Form and 47 works like ModelForm object : 48 49 >>> from couchdbkit.ext.django.forms import DocumentForm 50 51 # Create the form class. 52 >>> class ArticleForm(DocumentForm): 53 ... class Meta: 54 ... model = Article 55 56 # Creating a form to add an article. 57 >>> form = ArticleForm() 58 59 # Creating a form to change an existing article. 60 >>> article = Article.get(someid) 61 >>> form = ArticleForm(instance=article) 62 63 64 The generated Form class will have a form field for every model field. 65 Each document property has a corresponding default form field: 66 67 * StringProperty -> CharField, 68 * IntegerProperty -> IntegerField, 69 * DecimalProperty -> DecimalField, 70 * BooleanProperty -> BooleanField, 71 * FloatProperty -> FloatField, 72 * DateTimeProperty -> DateTimeField, 73 * DateProperty -> DateField, 74 * TimeProperty -> TimeField 75 76 77 More fields types will be supported soon. 78 """ 79 80 81 from django.utils.text import capfirst 82 from django.utils.datastructures import SortedDict 83 from django.forms.util import ValidationError, ErrorList 84 from django.forms.forms import BaseForm, get_declared_fields 85 from django.forms import fields as f 86 from django.forms.widgets import media_property 87 88 from . import schema 89 from ...schema import value_to_python 90 91 FIELDS_PROPERTES_MAPPING = { 92 "StringProperty": f.CharField, 93 "IntegerProperty": f.IntegerField, 94 "DecimalProperty": f.DecimalField, 95 "BooleanProperty": f.BooleanField, 96 "FloatProperty": f.FloatField, 97 "DateTimeProperty": f.DateTimeField, 98 "DateProperty": f.DateField, 99 "TimeProperty": f.TimeField 100 } 101103 """ 104 Returns a dict containing the data in ``instance`` suitable for passing as 105 a Form's ``initial`` keyword argument. 106 107 ``properties`` is an optional list of properties names. If provided, 108 only the named properties will be included in the returned dict. 109 110 ``exclude`` is an optional list of properties names. If provided, the named 111 properties will be excluded from the returned dict, even if they are listed 112 in the ``properties`` argument. 113 """ 114 # avoid a circular import 115 data = {} 116 for prop_name in instance._doc.keys(): 117 if properties and not prop_name in properties: 118 continue 119 if exclude and prop_name in exclude: 120 continue 121 data[prop_name] = instance[prop_name] 122 return data123125 """ 126 Returns a ``SortedDict`` containing form fields for the given document. 127 128 ``properties`` is an optional list of properties names. If provided, 129 only the named properties will be included in the returned properties. 130 131 ``exclude`` is an optional list of properties names. If provided, the named 132 properties will be excluded from the returned properties, even if 133 they are listed in the ``properties`` argument. 134 """ 135 field_list = [] 136 137 values = [] 138 if properties: 139 values = [document._properties[prop] for prop in properties if \ 140 prop in document._properties] 141 else: 142 values = document._properties.values() 143 values.sort(lambda a, b: cmp(a.creation_counter, b.creation_counter)) 144 145 for prop in values: 146 if properties and not prop.name in properties: 147 continue 148 if exclude and prop.name in exclude: 149 continue 150 property_class_name = prop.__class__.__name__ 151 if property_class_name in FIELDS_PROPERTES_MAPPING: 152 defaults = { 153 'required': prop.required, 154 'label': capfirst(prop.verbose_name), 155 } 156 157 if prop.default is not None: 158 defaults['initial'] = prop.default_value 159 160 if prop.choices: 161 if prop.default: 162 defaults['choices'] = prop.default_value() + list( 163 prop.choices) 164 defaults['coerce'] = prop.to_python 165 166 field_list.append((prop.name, 167 FIELDS_PROPERTES_MAPPING[property_class_name](**defaults))) 168 return SortedDict(field_list)169175172 self.document = getattr(options, 'document', None) 173 self.properties = getattr(options, 'properties', None) 174 self.exclude = getattr(options, 'exclude', None)210178 try: 179 parents = [b for b in bases if issubclass(b, DocumentForm)] 180 except NameError: 181 # We are defining ModelForm itself. 182 parents = None 183 184 declared_fields = get_declared_fields(bases, attrs, False) 185 new_class = super(DocumentFormMetaClass, cls).__new__(cls, name, bases, 186 attrs) 187 188 if not parents: 189 return new_class 190 191 if 'media' not in attrs: 192 new_class.media = media_property(new_class) 193 194 opts = new_class._meta = DocumentFormOptions(getattr(new_class, 195 'Meta', None)) 196 197 if opts.document: 198 # If a document is defined, extract form fields from it. 199 fields = fields_for_document(opts.document, opts.properties, 200 opts.exclude) 201 # Override default docuemnt fields with any custom declared ones 202 # (plus, include all the other declared fields). 203 fields.update(declared_fields) 204 else: 205 fields = declared_fields 206 207 new_class.declared_fields = declared_fields 208 new_class.base_fields = fields 209 return new_class212 """ Base Document Form object """ 213268 272214 - def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, 215 initial=None, error_class=ErrorList, label_suffix=":", 216 empty_permitted=False, instance=None):217 218 opts = self._meta 219 220 if instance is None: 221 self.instance = opts.document() 222 object_data = {} 223 else: 224 self.instance = instance 225 object_data = document_to_dict(instance, opts.properties, 226 opts.exclude) 227 228 if initial is not None: 229 object_data.update(initial) 230 231 super(BaseDocumentForm, self).__init__(data, files, auto_id, prefix, 232 object_data, error_class, 233 label_suffix, empty_permitted)234236 """ 237 Saves this ``form``'s cleaned_data into document instance 238 ``self.instance``. 239 240 If commit=True, then the changes to ``instance`` will be saved to the 241 database. Returns ``instance``. 242 """ 243 244 opts = self._meta 245 cleaned_data = self.cleaned_data.copy() 246 for prop_name in self.instance._doc.keys(): 247 if opts.properties and prop_name not in opts.properties: 248 continue 249 if opts.exclude and prop_name in opts.exclude: 250 continue 251 if prop_name in cleaned_data: 252 value = cleaned_data.pop(prop_name) 253 if value is not None: 254 setattr(self.instance, prop_name, value) 255 256 if dynamic: 257 for attr_name in cleaned_data.keys(): 258 if opts.exclude and attr_name in opts.exclude: 259 continue 260 value = cleaned_data[attr_name] 261 if value is not None: 262 setattr(self.instance, attr_name, value) 263 264 if commit: 265 self.instance.save() 266 267 return self.instance
Home | Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Fri Feb 18 10:31:29 2011 | http://epydoc.sourceforge.net |