PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/django/branches/attic/multiple-db-support/django/db/models/options.py

https://bitbucket.org/mirror/django/
Python | 284 lines | 267 code | 10 blank | 7 comment | 11 complexity | 8cec5454a7d08ba4a3081e199b7fb57f MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.conf import settings
  2. from django.db import connection_info, connections
  3. from django.db.models.related import RelatedObject
  4. from django.db.models.fields.related import ManyToManyRel
  5. from django.db.models.fields import AutoField, FieldDoesNotExist
  6. from django.db.models.loading import get_models
  7. from django.db.models.query import orderlist2sql
  8. from django.db.models import Manager
  9. from bisect import bisect
  10. import re
  11. import weakref
  12. # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
  13. get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
  14. DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
  15. 'unique_together', 'permissions', 'get_latest_by',
  16. 'order_with_respect_to', 'app_label')
  17. class Options(object):
  18. def __init__(self, meta):
  19. self.fields, self.many_to_many = [], []
  20. self.module_name, self.verbose_name = None, None
  21. self.verbose_name_plural = None
  22. self.db_table = ''
  23. self.ordering = []
  24. self.unique_together = []
  25. self.permissions = []
  26. self.object_name, self.app_label = None, None
  27. self.get_latest_by = None
  28. self.order_with_respect_to = None
  29. self.admin = None
  30. self.meta = meta
  31. self.pk = None
  32. self.has_auto_field = False
  33. self.one_to_one_field = None
  34. self.parents = []
  35. def contribute_to_class(self, cls, name):
  36. cls._meta = self
  37. self.installed = re.sub('\.models$', '', cls.__module__) in settings.INSTALLED_APPS
  38. # First, construct the default values for these options.
  39. self.object_name = cls.__name__
  40. self.module_name = self.object_name.lower()
  41. self.verbose_name = get_verbose_name(self.object_name)
  42. # Next, apply any overridden values from 'class Meta'.
  43. if self.meta:
  44. meta_attrs = self.meta.__dict__
  45. del meta_attrs['__module__']
  46. del meta_attrs['__doc__']
  47. for attr_name in DEFAULT_NAMES:
  48. setattr(self, attr_name, meta_attrs.pop(attr_name, getattr(self, attr_name)))
  49. # verbose_name_plural is a special case because it uses a 's'
  50. # by default.
  51. setattr(self, 'verbose_name_plural', meta_attrs.pop('verbose_name_plural', self.verbose_name + 's'))
  52. # Any leftover attributes must be invalid.
  53. if meta_attrs != {}:
  54. raise TypeError, "'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys())
  55. else:
  56. self.verbose_name_plural = self.verbose_name + 's'
  57. del self.meta
  58. def _prepare(self, model):
  59. if self.order_with_respect_to:
  60. self.order_with_respect_to = self.get_field(self.order_with_respect_to)
  61. self.ordering = ('_order',)
  62. else:
  63. self.order_with_respect_to = None
  64. if self.pk is None:
  65. auto = AutoField(verbose_name='ID', primary_key=True)
  66. auto.creation_counter = -1
  67. model.add_to_class('id', auto)
  68. # If the db_table wasn't provided, use the app_label + module_name.
  69. if not self.db_table:
  70. self.db_table = "%s_%s" % (self.app_label, self.module_name)
  71. # Keep a weakref to my model, for access to managers and such
  72. self._model = weakref.ref(model)
  73. def add_field(self, field):
  74. # Insert the given field in the order in which it was created, using
  75. # the "creation_counter" attribute of the field.
  76. # Move many-to-many related fields from self.fields into self.many_to_many.
  77. if field.rel and isinstance(field.rel, ManyToManyRel):
  78. self.many_to_many.insert(bisect(self.many_to_many, field), field)
  79. else:
  80. self.fields.insert(bisect(self.fields, field), field)
  81. if not self.pk and field.primary_key:
  82. self.pk = field
  83. def __repr__(self):
  84. return '<Options for %s>' % self.object_name
  85. def __str__(self):
  86. return "%s.%s" % (self.app_label, self.module_name)
  87. def get_field(self, name, many_to_many=True):
  88. "Returns the requested field by name. Raises FieldDoesNotExist on error."
  89. to_search = many_to_many and (self.fields + self.many_to_many) or self.fields
  90. for f in to_search:
  91. if f.name == name:
  92. return f
  93. raise FieldDoesNotExist, '%s has no field named %r' % (self.object_name, name)
  94. def get_default_manager(self):
  95. model = self._model()
  96. if model is None:
  97. raise ReferenceError("Model no longer available in %s" % self)
  98. return model._default_manager
  99. def get_order_sql(self, table_prefix=''):
  100. "Returns the full 'ORDER BY' clause for this object, according to self.ordering."
  101. if not self.ordering: return ''
  102. pre = table_prefix and (table_prefix + '.') or ''
  103. return 'ORDER BY ' + orderlist2sql(self.ordering, self, pre)
  104. def get_add_permission(self):
  105. return 'add_%s' % self.object_name.lower()
  106. def get_change_permission(self):
  107. return 'change_%s' % self.object_name.lower()
  108. def get_delete_permission(self):
  109. return 'delete_%s' % self.object_name.lower()
  110. def get_all_related_objects(self):
  111. try: # Try the cache first.
  112. return self._all_related_objects
  113. except AttributeError:
  114. rel_objs = []
  115. for klass in get_models():
  116. for f in klass._meta.fields:
  117. if f.rel and self == f.rel.to._meta:
  118. rel_objs.append(RelatedObject(f.rel.to, klass, f))
  119. self._all_related_objects = rel_objs
  120. return rel_objs
  121. def get_followed_related_objects(self, follow=None):
  122. if follow == None:
  123. follow = self.get_follow()
  124. return [f for f in self.get_all_related_objects() if follow.get(f.name, None)]
  125. def get_data_holders(self, follow=None):
  126. if follow == None:
  127. follow = self.get_follow()
  128. return [f for f in self.fields + self.many_to_many + self.get_all_related_objects() if follow.get(f.name, None)]
  129. def get_follow(self, override=None):
  130. follow = {}
  131. for f in self.fields + self.many_to_many + self.get_all_related_objects():
  132. if override and override.has_key(f.name):
  133. child_override = override[f.name]
  134. else:
  135. child_override = None
  136. fol = f.get_follow(child_override)
  137. if fol != None:
  138. follow[f.name] = fol
  139. return follow
  140. def get_all_related_many_to_many_objects(self):
  141. try: # Try the cache first.
  142. return self._all_related_many_to_many_objects
  143. except AttributeError:
  144. rel_objs = []
  145. for klass in get_models():
  146. for f in klass._meta.many_to_many:
  147. if f.rel and self == f.rel.to._meta:
  148. rel_objs.append(RelatedObject(f.rel.to, klass, f))
  149. self._all_related_many_to_many_objects = rel_objs
  150. return rel_objs
  151. def get_ordered_objects(self):
  152. "Returns a list of Options objects that are ordered with respect to this object."
  153. if not hasattr(self, '_ordered_objects'):
  154. objects = []
  155. # TODO
  156. #for klass in get_models(get_app(self.app_label)):
  157. # opts = klass._meta
  158. # if opts.order_with_respect_to and opts.order_with_respect_to.rel \
  159. # and self == opts.order_with_respect_to.rel.to._meta:
  160. # objects.append(opts)
  161. self._ordered_objects = objects
  162. return self._ordered_objects
  163. def has_field_type(self, field_type, follow=None):
  164. """
  165. Returns True if this object's admin form has at least one of the given
  166. field_type (e.g. FileField).
  167. """
  168. # TODO: follow
  169. if not hasattr(self, '_field_types'):
  170. self._field_types = {}
  171. if not self._field_types.has_key(field_type):
  172. try:
  173. # First check self.fields.
  174. for f in self.fields:
  175. if isinstance(f, field_type):
  176. raise StopIteration
  177. # Failing that, check related fields.
  178. for related in self.get_followed_related_objects(follow):
  179. for f in related.opts.fields:
  180. if isinstance(f, field_type):
  181. raise StopIteration
  182. except StopIteration:
  183. self._field_types[field_type] = True
  184. else:
  185. self._field_types[field_type] = False
  186. return self._field_types[field_type]
  187. class AdminOptions(object):
  188. def __init__(self, fields=None, js=None, list_display=None, list_display_links=None, list_filter=None,
  189. date_hierarchy=None, save_as=False, ordering=None, search_fields=None,
  190. save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
  191. self.fields = fields
  192. self.js = js or []
  193. self.list_display = list_display or ['__str__']
  194. self.list_display_links = list_display_links or []
  195. self.list_filter = list_filter or []
  196. self.date_hierarchy = date_hierarchy
  197. self.save_as, self.ordering = save_as, ordering
  198. self.search_fields = search_fields or []
  199. self.save_on_top = save_on_top
  200. self.list_select_related = list_select_related
  201. self.list_per_page = list_per_page
  202. self.manager = manager or Manager()
  203. def get_field_sets(self, opts):
  204. "Returns a list of AdminFieldSet objects for this AdminOptions object."
  205. if self.fields is None:
  206. field_struct = ((None, {'fields': [f.name for f in opts.fields + opts.many_to_many if f.editable and not isinstance(f, AutoField)]}),)
  207. else:
  208. field_struct = self.fields
  209. new_fieldset_list = []
  210. for fieldset in field_struct:
  211. fs_options = fieldset[1]
  212. classes = fs_options.get('classes', ())
  213. description = fs_options.get('description', '')
  214. new_fieldset_list.append(AdminFieldSet(fieldset[0], classes,
  215. opts.get_field, fs_options['fields'], description))
  216. return new_fieldset_list
  217. def contribute_to_class(self, cls, name):
  218. cls._meta.admin = self
  219. # Make sure the admin manager has access to the model
  220. self.manager.model = cls
  221. class AdminFieldSet(object):
  222. def __init__(self, name, classes, field_locator_func, line_specs, description):
  223. self.name = name
  224. self.field_lines = [AdminFieldLine(field_locator_func, line_spec) for line_spec in line_specs]
  225. self.classes = classes
  226. self.description = description
  227. def __repr__(self):
  228. return "FieldSet: (%s, %s)" % (self.name, self.field_lines)
  229. def bind(self, field_mapping, original, bound_field_set_class):
  230. return bound_field_set_class(self, field_mapping, original)
  231. def __iter__(self):
  232. for field_line in self.field_lines:
  233. yield field_line
  234. def __len__(self):
  235. return len(self.field_lines)
  236. class AdminFieldLine(object):
  237. def __init__(self, field_locator_func, linespec):
  238. if isinstance(linespec, basestring):
  239. self.fields = [field_locator_func(linespec)]
  240. else:
  241. self.fields = [field_locator_func(field_name) for field_name in linespec]
  242. def bind(self, field_mapping, original, bound_field_line_class):
  243. return bound_field_line_class(self, field_mapping, original)
  244. def __iter__(self):
  245. for field in self.fields:
  246. yield field
  247. def __len__(self):
  248. return len(self.fields)