4
4
5
5
from django .db .models .fields import FieldDoesNotExist
6
6
from django .utils .text import capfirst
7
- # from django.db.models.options import get_verbose_name
8
- from django .utils .functional import LazyObject
7
+ from django .utils .functional import LazyObject , new_method_proxy
8
+ try :
9
+ # New in Django 1.7+
10
+ from django .utils .text import camel_case_to_spaces
11
+ except ImportError :
12
+ # Backwards compatibility
13
+ from django .db .models .options import get_verbose_name as camel_case_to_spaces
9
14
from django .conf import settings
10
-
11
15
from mongoengine .fields import ReferenceField , ListField
12
16
13
- # TODO: validate it. This is added instead of django get_verbose_name
14
- import re
15
- get_verbose_name = lambda class_name : re .sub ('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))' , ' \\ 1' , class_name ).lower ().strip ()
16
17
17
18
def patch_document (function , instance , bound = True ):
18
19
if bound :
@@ -23,7 +24,7 @@ def patch_document(function, instance, bound=True):
23
24
24
25
25
26
def create_verbose_name (name ):
26
- name = get_verbose_name (name )
27
+ name = camel_case_to_spaces (name )
27
28
name = name .replace ('_' , ' ' )
28
29
return name
29
30
@@ -50,26 +51,10 @@ def to(self, value):
50
51
class PkWrapper (object ):
51
52
editable = False
52
53
fake = False
53
- # TODO: check it. Probably will be used to accomplished django 1.7
54
- # rel = None
55
- # blank = True
56
- # null = True
57
- # verbose_name = None
58
- # help_text = None
59
- # flatchoices = False
60
54
61
55
def __init__ (self , wrapped ):
62
56
self .obj = wrapped
63
57
64
- # def has_default(self):
65
- # return False
66
- #
67
- # def _get_val_from_obj(self, obj):
68
- # return obj
69
- #
70
- # def value_to_string(self, obj):
71
- # return str(obj)
72
-
73
58
def __getattr__ (self , attr ):
74
59
if attr in dir (self .obj ):
75
60
return getattr (self .obj , attr )
@@ -84,39 +69,27 @@ def __setattr__(self, attr, value):
84
69
class LazyDocumentMetaWrapper (LazyObject ):
85
70
_document = None
86
71
_meta = None
87
-
72
+
88
73
def __init__ (self , document ):
89
74
self ._document = document
90
75
self ._meta = document ._meta
91
76
super (LazyDocumentMetaWrapper , self ).__init__ ()
92
-
77
+
93
78
def _setup (self ):
94
79
self ._wrapped = DocumentMetaWrapper (self ._document , self ._meta )
95
-
80
+
96
81
def __setattr__ (self , name , value ):
97
- if name in ["_document" , "_meta" ,]:
82
+ if name in ["_document" , "_meta" , ]:
98
83
object .__setattr__ (self , name , value )
99
84
else :
100
85
super (LazyDocumentMetaWrapper , self ).__setattr__ (name , value )
101
-
102
- def __dir__ (self ):
103
- return self ._wrapped .__dir__ ()
104
-
105
- def __getitem__ (self , key ):
106
- return self ._wrapped .__getitem__ (key )
107
-
108
- def __setitem__ (self , key , value ):
109
- return self ._wrapped .__getitem__ (key )
110
-
111
- def __delitem__ (self , key ):
112
- return self ._wrapped .__delitem__ (key )
113
-
114
- def __len__ (self ):
115
- return self ._wrapped .__len__ ()
116
-
86
+
87
+ __len__ = new_method_proxy (len )
88
+
89
+ @new_method_proxy
117
90
def __contains__ (self , key ):
118
- return self . _wrapped . __contains__ ( key )
119
-
91
+ return key in self
92
+
120
93
121
94
class DocumentMetaWrapper (MutableMapping ):
122
95
"""
@@ -129,12 +102,12 @@ class DocumentMetaWrapper(MutableMapping):
129
102
pk = None
130
103
pk_name = None
131
104
_app_label = None
132
- _app_config = None
133
105
model_name = None
134
106
_verbose_name = None
135
107
has_auto_field = False
136
108
object_name = None
137
109
proxy = []
110
+ proxied_children = []
138
111
parents = {}
139
112
many_to_many = []
140
113
_field_cache = None
@@ -154,10 +127,18 @@ def __init__(self, document, meta=None):
154
127
self .concrete_model = document
155
128
if meta is None :
156
129
meta = getattr (document , '_meta' , {})
130
+ if not 'app_label' in meta :
131
+ meta ['app_label' ] = document .__module__ .split ('.' )[0 ]
132
+ if not 'app_config' in meta :
133
+ # TODO: this needs improvements
134
+ meta ['app_config' ] = dict ()
135
+ if not 'verbose_name' in meta :
136
+ meta ['app_config' ]['verbose_name' ] = meta ['app_label' ].replace ('_' , ' ' ).capitalize ()
157
137
if isinstance (meta , LazyDocumentMetaWrapper ):
158
138
meta = meta ._meta
159
139
self ._meta = meta
160
140
141
+
161
142
try :
162
143
self .object_name = self .document .__name__
163
144
except AttributeError :
@@ -170,7 +151,7 @@ def __init__(self, document, meta=None):
170
151
self ._setup_document_fields ()
171
152
# Setup self.pk if the document has an id_field in it's meta
172
153
# if it doesn't have one it's an embedded document
173
- #if 'id_field' in self._meta:
154
+ # if 'id_field' in self._meta:
174
155
# self.pk_name = self._meta['id_field']
175
156
self ._init_pk ()
176
157
@@ -181,12 +162,23 @@ def _setup_document_fields(self):
181
162
if not hasattr (f , 'rel' ):
182
163
# need a bit more for actual reference fields here
183
164
if isinstance (f , ReferenceField ):
165
+ # FIXME: Probably broken in Django 1.7
184
166
f .rel = Relation (f .document_type )
185
- elif isinstance (f , ListField ) and \
186
- isinstance (f .field , ReferenceField ):
167
+ f .is_relation = True
168
+ elif isinstance (f , ListField ) and isinstance (f .field , ReferenceField ):
169
+ # FIXME: Probably broken in Django 1.7
187
170
f .field .rel = Relation (f .field .document_type )
171
+ f .field .is_relation = True
188
172
else :
173
+ f .many_to_many = None
174
+ f .many_to_one = None
175
+ f .one_to_many = None
176
+ f .one_to_one = None
177
+ f .related_model = None
178
+
179
+ # FIXME: No longer used in Django 1.7?
189
180
f .rel = None
181
+ f .is_relation = False
190
182
if not hasattr (f , 'verbose_name' ) or f .verbose_name is None :
191
183
f .verbose_name = capfirst (create_verbose_name (f .name ))
192
184
if not hasattr (f , 'flatchoices' ):
@@ -202,6 +194,8 @@ def _setup_document_fields(self):
202
194
isinstance (f .document_type ._meta , (DocumentMetaWrapper , LazyDocumentMetaWrapper )) and \
203
195
self .document != f .document_type :
204
196
f .document_type ._meta = LazyDocumentMetaWrapper (f .document_type )
197
+ if not hasattr (f , 'auto_created' ):
198
+ f .auto_created = False
205
199
206
200
def _init_pk (self ):
207
201
"""
@@ -217,58 +211,51 @@ def _init_pk(self):
217
211
pk_field = None
218
212
self .pk = PkWrapper (pk_field )
219
213
220
- def _get_pk_val (self ):
221
- return self ._pk_val
214
+ def _get_pk_val (obj ):
215
+ return obj .pk
216
+ patch_document (_get_pk_val , self .document , False ) # document is a class...
222
217
223
218
if pk_field is not None :
224
219
self .pk .name = self .pk_name
225
220
self .pk .attname = self .pk_name
226
- self .document ._pk_val = pk_field
227
- patch_document (_get_pk_val , self .document )
228
221
else :
229
222
self .pk .fake = True
230
223
# this is used in the admin and used to determine if the admin
231
224
# needs to add a hidden pk field. It does not for embedded fields.
232
225
# So we pretend to have an editable pk field and just ignore it otherwise
233
226
self .pk .editable = True
234
-
227
+
235
228
@property
236
229
def app_label (self ):
237
230
if self ._app_label is None :
238
- model_module = sys .modules [self .document .__module__ ]
239
- # TODO: test it.
240
- self ._app_label = model_module .__name__ .split ('.' )[0 ]
231
+ if self ._meta .get ('app_label' ):
232
+ self ._app_label = self ._meta ["app_label" ]
233
+ else :
234
+ model_module = sys .modules [self .document .__module__ ]
235
+ self ._app_label = model_module .__name__ .split ('.' )[- 2 ]
241
236
return self ._app_label
242
237
243
- @property
244
- def app_config (self ):
245
- if self ._app_config is None :
246
- from django .apps import apps
247
- self ._app_config = apps .get_app_config (self .app_label )
248
- # self._meta['app_config'] = self._app_config
249
- return self ._app_config
250
-
251
238
@property
252
239
def verbose_name (self ):
253
240
"""
254
241
Returns the verbose name of the document.
255
-
242
+
256
243
Checks the original meta dict first. If it is not found
257
244
then generates a verbose name from the object name.
258
245
"""
259
246
if self ._verbose_name is None :
260
247
verbose_name = self ._meta .get ('verbose_name' , self .object_name )
261
248
self ._verbose_name = capfirst (create_verbose_name (verbose_name ))
262
249
return self ._verbose_name
263
-
250
+
264
251
@property
265
252
def verbose_name_raw (self ):
266
253
return self .verbose_name
267
-
254
+
268
255
@property
269
256
def verbose_name_plural (self ):
270
257
return "%ss" % self .verbose_name
271
-
258
+
272
259
def get_add_permission (self ):
273
260
return 'add_%s' % self .object_name .lower ()
274
261
@@ -277,10 +264,10 @@ def get_change_permission(self):
277
264
278
265
def get_delete_permission (self ):
279
266
return 'delete_%s' % self .object_name .lower ()
280
-
267
+
281
268
def get_ordered_objects (self ):
282
269
return []
283
-
270
+
284
271
def get_field_by_name (self , name ):
285
272
"""
286
273
Returns the (field_object, model, direct, m2m), where field_object is
@@ -300,13 +287,16 @@ def get_field_by_name(self, name):
300
287
else :
301
288
raise FieldDoesNotExist ('%s has no field named %r' %
302
289
(self .object_name , name ))
303
-
290
+
304
291
def get_field (self , name , many_to_many = True ):
305
292
"""
306
293
Returns the requested field by name. Raises FieldDoesNotExist on error.
307
294
"""
308
295
return self .get_field_by_name (name )[0 ]
309
-
296
+
297
+ def get_fields (self , include_hidden = False ):
298
+ return self .document ._fields .values ()
299
+
310
300
@property
311
301
def swapped (self ):
312
302
"""
@@ -315,7 +305,7 @@ def swapped(self):
315
305
316
306
For historical reasons, model name lookups using get_model() are
317
307
case insensitive, so we make sure we are case insensitive here.
318
-
308
+
319
309
NOTE: Not sure this is actually usefull for documents. So at the
320
310
moment it's really only here because the admin wants it. It might
321
311
prove usefull for someone though, so it's more then just a dummy.
@@ -337,31 +327,28 @@ def swapped(self):
337
327
not in (None , model_label ):
338
328
return swapped_for
339
329
return None
340
-
330
+
341
331
def __getattr__ (self , name ):
342
332
if name in self ._deprecated_attrs :
343
333
return getattr (self , self ._deprecated_attrs .get (name ))
344
-
334
+
345
335
try :
346
- # TODO: check it. It seems that is needed return empty string instead of an error.
347
- # print "####### REAL META"
348
- # print self._meta
349
336
return self ._meta [name ]
350
337
except KeyError :
351
- return ''
352
-
338
+ raise AttributeError
339
+
353
340
def __setattr__ (self , name , value ):
354
341
if not hasattr (self , name ):
355
342
self ._meta [name ] = value
356
343
else :
357
344
super (DocumentMetaWrapper , self ).__setattr__ (name , value )
358
-
345
+
359
346
def __contains__ (self , key ):
360
347
return key in self ._meta
361
-
348
+
362
349
def __getitem__ (self , key ):
363
350
return self ._meta [key ]
364
-
351
+
365
352
def __setitem__ (self , key , value ):
366
353
self ._meta [key ] = value
367
354
@@ -374,15 +361,21 @@ def __iter__(self):
374
361
def __len__ (self ):
375
362
return self ._meta .__len__ ()
376
363
364
+ def __cmp__ (self , other ):
365
+ return hash (self ) == hash (other )
366
+
367
+ def __hash__ (self ):
368
+ return id (self )
369
+
377
370
def get (self , key , default = None ):
378
371
try :
379
372
return self .__getitem__ (key )
380
373
except KeyError :
381
374
return default
382
-
375
+
383
376
def get_parent_list (self ):
384
377
return []
385
-
378
+
386
379
def get_all_related_objects (self , * args , ** kwargs ):
387
380
return []
388
381
0 commit comments