|
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 |