app/soc/models/base.py
changeset 110 e310681d5509
child 274 56e1c1721299
equal deleted inserted replaced
109:620f9b141567 110:e310681d5509
       
     1 #!/usr/bin/python2.5
       
     2 #
       
     3 # Copyright 2008 the Melange authors.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 # 
       
     9 #   http://www.apache.org/licenses/LICENSE-2.0
       
    10 # 
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 
       
    17 """Module containing enhanced db.Model classes.
       
    18 
       
    19 The classes in this module are intended to serve as base classes for all
       
    20 Melange Datastore Models.
       
    21 """
       
    22 
       
    23 __authors__ = [
       
    24   '"Todd Larsen" <tlarsen@google.com>',
       
    25 ]
       
    26 
       
    27 
       
    28 from google.appengine.ext import db
       
    29 
       
    30 from soc.views.helpers import forms_helpers
       
    31 
       
    32 
       
    33 class ModelWithFieldAttributes(db.Model):
       
    34   """A db.Model extension that provides access to Model properties attributes.
       
    35   
       
    36   Due to the way the Property class in Google App Engine implements __get__()
       
    37   and __set__(), it is not possible to access attributes of Model properties,
       
    38   such as verbose_name, from within a Django template.  This class works
       
    39   around that limitation by creating an inner Form class per Model class,
       
    40   since an unbound Form object contains (most of?) the property attributes
       
    41   attached to each corresponding Form field.
       
    42   
       
    43   Some are attributes are renamed during the conversion from a Model Property
       
    44   to a Form field; for example, verbose_name becomes label.  This is tolerable
       
    45   because any actual Form code refers to these new names, so they are should
       
    46   be familiar to view creators.  
       
    47   """
       
    48 
       
    49   _fields_cache = None
       
    50   
       
    51   @classmethod
       
    52   def fields(cls):
       
    53     """Called by the Django template engine during template instantiation.
       
    54     
       
    55     Since the attribute names use the Form fields naming instead of the
       
    56     Property attribute naming, accessing, for example:
       
    57       {{ entity.property.verbose_name }}
       
    58     is accomplished using:
       
    59       {{ entity.fields.property.label }}
       
    60     
       
    61     Args:
       
    62       cls: Model class, so that each Model class can create its own
       
    63         unbound Form the first time fields() is called by the Django
       
    64         template engine.
       
    65  
       
    66     Returns:
       
    67       A (created-on-first-use) unbound Form object that can be used to
       
    68       access Property attributes that are not accessible from the
       
    69       Property itself via the Model entity.
       
    70     """
       
    71     if not cls._fields_cache or (cls != cls._fields_cache.__class__.Meta.model):
       
    72       class FieldsProxy(forms_helpers.DbModelForm):
       
    73         """Form used as a proxy to access User model properties attributes.
       
    74         """
       
    75       
       
    76         class Meta:
       
    77           """Inner Meta class that pairs the User Model with this "form".
       
    78           """
       
    79           #: db.Model subclass for which to access model properties attributes
       
    80           model = cls
       
    81       
       
    82       cls._fields_cache = FieldsProxy()
       
    83 
       
    84     return cls._fields_cache