Changeset 7126
- Timestamp:
- 02/17/08 12:47:57 (3 months ago)
- Files:
-
- django/branches/queryset-refactor/django/core/management/sql.py (modified) (7 diffs)
- django/branches/queryset-refactor/django/core/management/validation.py (modified) (6 diffs)
- django/branches/queryset-refactor/django/db/models/base.py (modified) (9 diffs)
- django/branches/queryset-refactor/django/db/models/fields/__init__.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/fields/related.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/manager.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/options.py (modified) (12 diffs)
- django/branches/queryset-refactor/django/db/models/sql/query.py (modified) (5 diffs)
- django/branches/queryset-refactor/docs/model-api.txt (modified) (1 diff)
- django/branches/queryset-refactor/tests/modeltests/model_inheritance/models.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/django/core/management/sql.py
r7004 r7126 27 27 for model in models.get_models(app): 28 28 tables.append(model._meta.db_table) 29 tables.extend([f.m2m_db_table() for f in model._meta. many_to_many])29 tables.extend([f.m2m_db_table() for f in model._meta.local_many_to_many]) 30 30 if only_existing: 31 31 existing = table_list() … … 55 55 for app in apps: 56 56 for model in models.get_models(app): 57 for f in model._meta. fields:57 for f in model._meta.local_fields: 58 58 if isinstance(f, models.AutoField): 59 59 sequence_list.append({'table': model._meta.db_table, 'column': f.column}) 60 60 break # Only one AutoField is allowed per model, so don't bother continuing. 61 61 62 for f in model._meta. many_to_many:62 for f in model._meta.local_many_to_many: 63 63 sequence_list.append({'table': f.m2m_db_table(), 'column': None}) 64 64 … … 148 148 # The table exists, so it needs to be dropped 149 149 opts = model._meta 150 for f in opts. fields:150 for f in opts.local_fields: 151 151 if f.rel and f.rel.to not in to_delete: 152 152 references_to_delete.setdefault(f.rel.to, []).append( (model, f) ) … … 180 180 for model in app_models: 181 181 opts = model._meta 182 for f in opts. many_to_many:182 for f in opts.local_many_to_many: 183 183 if isinstance(f.rel, generic.GenericRel): 184 184 continue … … 257 257 qn = connection.ops.quote_name 258 258 inline_references = connection.features.inline_fk_references 259 for f in opts. fields:259 for f in opts.local_fields: 260 260 col_type = f.db_type() 261 261 tablespace = f.db_tablespace or opts.db_tablespace … … 352 352 qn = connection.ops.quote_name 353 353 inline_references = connection.features.inline_fk_references 354 for f in opts. many_to_many:354 for f in opts.local_many_to_many: 355 355 if not isinstance(f.rel, generic.GenericRel): 356 356 tablespace = f.db_tablespace or opts.db_tablespace … … 459 459 460 460 qn = connection.ops.quote_name 461 for f in model._meta. fields:461 for f in model._meta.local_fields: 462 462 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): 463 463 unique = f.unique and 'UNIQUE ' or '' django/branches/queryset-refactor/django/core/management/validation.py
r6857 r7126 33 33 34 34 # Do field-specific validation. 35 for f in opts. fields:35 for f in opts.local_fields: 36 36 if f.name == 'id' and not f.primary_key and opts.pk.name == 'id': 37 37 e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name) … … 70 70 e.add(opts, '"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) 71 71 72 # Check to see if the related field will clash with any 73 # existingfields, m2m fields, m2m related objects or related objects72 # Check to see if the related field will clash with any existing 73 # fields, m2m fields, m2m related objects or related objects 74 74 if f.rel: 75 75 if f.rel.to not in models.get_models(): … … 88 88 if r.name == rel_query_name: 89 89 e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) 90 for r in rel_opts. many_to_many:90 for r in rel_opts.local_many_to_many: 91 91 if r.name == rel_name: 92 92 e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) … … 105 105 e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) 106 106 107 for i, f in enumerate(opts. many_to_many):107 for i, f in enumerate(opts.local_many_to_many): 108 108 # Check to see if the related m2m field will clash with any 109 # existing fields, m2m fields, m2m related objects or related objects 109 # existing fields, m2m fields, m2m related objects or related 110 # objects 110 111 if f.rel.to not in models.get_models(): 111 112 e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, f.rel.to)) … … 118 119 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() 119 120 rel_query_name = f.related_query_name() 120 # If rel_name is none, there is no reverse accessor .121 # (This only occurs for symmetrical m2m relations to self).122 # If this is the case, there are no clashes to check for this field, as123 # there areno reverse descriptors for this field.121 # If rel_name is none, there is no reverse accessor (this only 122 # occurs for symmetrical m2m relations to self). If this is the 123 # case, there are no clashes to check for this field, as there are 124 # no reverse descriptors for this field. 124 125 if rel_name is not None: 125 126 for r in rel_opts.fields: … … 128 129 if r.name == rel_query_name: 129 130 e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) 130 for r in rel_opts. many_to_many:131 for r in rel_opts.local_many_to_many: 131 132 if r.name == rel_name: 132 133 e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) django/branches/queryset-refactor/django/db/models/base.py
r7124 r7126 1 import types 2 import sys 3 import os 4 from itertools import izip 5 1 6 import django.db.models.manipulators 2 7 import django.db.models.manager … … 4 9 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned 5 10 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist 6 from django.db.models.fields.related import OneToOneRel, ManyToOneRel 11 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 7 12 from django.db.models.query import delete_objects, Q 8 13 from django.db.models.options import Options, AdminOptions … … 15 20 from django.utils.encoding import smart_str, force_unicode, smart_unicode 16 21 from django.conf import settings 17 from itertools import izip18 import types19 import sys20 import os21 22 22 23 class ModelBase(type): … … 26 27 try: 27 28 parents = [b for b in bases if issubclass(b, Model)] 28 if not parents:29 return super(ModelBase, cls).__new__(cls, name, bases, attrs)30 29 except NameError: 31 30 # 'Model' isn't defined yet, meaning we're looking at Django's own 32 31 # Model class, defined below. 32 parents = [] 33 if not parents: 33 34 return super(ModelBase, cls).__new__(cls, name, bases, attrs) 34 35 35 36 # Create the class. 36 37 new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')}) 37 new_class.add_to_class('_meta', Options(attrs.pop('Meta', None))) 38 meta = attrs.pop('Meta', None) 39 # FIXME: Promote Meta to a newstyle class before attaching it to the 40 # model. 41 ## if meta: 42 ## new_class.Meta = meta 43 new_class.add_to_class('_meta', Options(meta)) 44 # FIXME: Need to be smarter here. Exception is an old-style class in 45 # Python <= 2.4, new-style in Python 2.5+. This construction is only 46 # really correct for old-style classes. 38 47 new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {})) 39 new_class.add_to_class('MultipleObjectsReturned', 40 types.ClassType('MultipleObjectsReturned', (MultipleObjectsReturned, ), {})) 41 42 # Build complete list of parents48 new_class.add_to_class('MultipleObjectsReturned', types.ClassType('MultipleObjectsReturned', (MultipleObjectsReturned, ), {})) 49 50 # Do the appropriate setup for any model parents. 51 abstract_parents = [] 43 52 for base in parents: 44 # Things without _meta aren't functional models, so they're 45 # uninteresting parents. 46 if hasattr(base, '_meta'): 47 new_class._meta.parents.append(base) 48 new_class._meta.parents.extend(base._meta.parents) 49 50 53 if not hasattr(base, '_meta'): 54 # Things without _meta aren't functional models, so they're 55 # uninteresting parents. 56 continue 57 if not base._meta.abstract: 58 attr_name = '%s_ptr' % base._meta.module_name 59 field = OneToOneField(base, name=attr_name, auto_created=True) 60 new_class.add_to_class(attr_name, field) 61 new_class._meta.parents[base] = field 62 else: 63 abstract_parents.append(base) 64 65 if getattr(new_class, '_default_manager', None) is not None: 66 # We have a parent who set the default manager. We need to override 67 # this. 68 new_class._default_manager = None 51 69 if getattr(new_class._meta, 'app_label', None) is None: 52 70 # Figure out the app_label by looking one level up. … … 64 82 new_class.add_to_class(obj_name, obj) 65 83 66 # Add Fields inherited from parents 67 for parent in new_class._meta.parents: 68 for field in parent._meta.fields: 69 # Only add parent fields if they aren't defined for this class. 70 try: 71 new_class._meta.get_field(field.name) 72 except FieldDoesNotExist: 73 field.contribute_to_class(new_class, field.name) 84 for parent in abstract_parents: 85 names = [f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many] 86 for field in parent._meta.local_fields: 87 if field.name in names: 88 raise TypeError('Local field %r in class %r clashes with field of similar name from abstract base class %r' 89 % (field.name, name, parent.__name__)) 90 new_class.add_to_class(field.name, field) 91 92 if new_class._meta.abstract: 93 # Abstract base models can't be instantiated and don't appear in 94 # the list of models for an app. We do the final setup for them a 95 # little differently from normal models. 96 return new_class 74 97 75 98 new_class._prepare() 76 77 99 register_models(new_class._meta.app_label, new_class) 100 78 101 # Because of the way imports happen (recursively), we may or may not be 79 # the first class for this modelto register with the framework. There80 # should only be one class for each model, so we mustalways return the102 # the first time this model tries to register with the framework. There 103 # should only be one class for each model, so we always return the 81 104 # registered version. 82 105 return get_model(new_class._meta.app_label, name, False) … … 114 137 __metaclass__ = ModelBase 115 138 116 def _get_pk_val(self): 117 return getattr(self, self._meta.pk.attname) 139 def _get_pk_val(self, meta=None): 140 if not meta: 141 meta = self._meta 142 return getattr(self, meta.pk.attname) 118 143 119 144 def _set_pk_val(self, value): … … 208 233 dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self) 209 234 210 def save(self, raw=False): 211 dispatcher.send(signal=signals.pre_save, sender=self.__class__, 212 instance=self, raw=raw) 213 214 non_pks = [f for f in self._meta.fields if not f.primary_key] 235 def save(self, raw=False, cls=None): 236 if not cls: 237 dispatcher.send(signal=signals.pre_save, sender=self.__class__, 238 instance=self, raw=raw) 239 cls = self.__class__ 240 meta = self._meta 241 signal = True 242 else: 243 meta = cls._meta 244 signal = False 245 246 for parent, field in meta.parents.items(): 247 self.save(raw, parent) 248 setattr(self, field.attname, self._get_pk_val(parent._meta)) 249 250 non_pks = [f for f in self._meta.local_fields if not f.primary_key] 215 251 216 252 # First, try an UPDATE. If that doesn't update anything, do an INSERT. 217 pk_val = self._get_pk_val( )253 pk_val = self._get_pk_val(meta) 218 254 # Note: the comparison with '' is required for compatibility with 219 255 # oldforms-style model creation. 220 256 pk_set = pk_val is not None and smart_unicode(pk_val) != u'' 221 257 record_exists = True 222 manager = self.__class__._default_manager258 manager = cls._default_manager 223 259 if pk_set: 224 260 # Determine whether a record with the primary key already exists. … … 232 268 if not pk_set or not record_exists: 233 269 if not pk_set: 234 values = [(f.name, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in self._meta.fields if not isinstance(f, AutoField)]235 else: 236 values = [(f.name, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in self._meta.fields]237 238 if self._meta.order_with_respect_to:239 field = self._meta.order_with_respect_to270 values = [(f.name, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)] 271 else: 272 values = [(f.name, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields] 273 274 if meta.order_with_respect_to: 275 field = meta.order_with_respect_to 240 276 values.append(('_order', manager.filter(**{field.name: getattr(self, field.attname)}).count())) 241 277 record_exists = False 242 278 243 update_pk = bool( self._meta.has_auto_field and not pk_set)279 update_pk = bool(meta.has_auto_field and not pk_set) 244 280 if values: 245 281 # Create a new record. … … 251 287 252 288 if update_pk: 253 setattr(self, self._meta.pk.attname, result)289 setattr(self, meta.pk.attname, result) 254 290 transaction.commit_unless_managed() 255 291 256 # Run any post-save hooks. 257 dispatcher.send(signal=signals.post_save, sender=self.__class__, 258 instance=self, created=(not record_exists), raw=raw) 292 if signal: 293 # Run any post-save hooks. 294 dispatcher.send(signal=signals.post_save, sender=self.__class__, 295 instance=self, created=(not record_exists), raw=raw) 259 296 260 297 save.alters_data = True django/branches/queryset-refactor/django/db/models/fields/__init__.py
r7029 r7126 76 76 empty_strings_allowed = True 77 77 78 # Tracks each time a Field instance is created. Used to retain order. 78 # These track each time a Field instance is created. Used to retain order. 79 # The auto_creation_counter is used for fields that Django implicitly 80 # creates, creation_counter is used for all user-specified fields. 79 81 creation_counter = 0 82 auto_creation_counter = -1 80 83 81 84 def __init__(self, verbose_name=None, name=None, primary_key=False, 82 max_length=None, unique=False, blank=False, null=False, db_index=False, 83 core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True, 84 prepopulate_from=None, unique_for_date=None, unique_for_month=None, 85 unique_for_year=None, validator_list=None, choices=None, radio_admin=None, 86 help_text='', db_column=None, db_tablespace=None): 85 max_length=None, unique=False, blank=False, null=False, 86 db_index=False, core=False, rel=None, default=NOT_PROVIDED, 87 editable=True, serialize=True, prepopulate_from=None, 88 unique_for_date=None, unique_for_month=None, unique_for_year=None, 89 validator_list=None, choices=None, radio_admin=None, help_text='', 90 db_column=None, db_tablespace=None, auto_created=False): 87 91 self.name = name 88 92 self.verbose_name = verbose_name … … 110 114 self.db_index = db_index 111 115 112 # Increase the creation counter, and save our local copy. 113 self.creation_counter = Field.creation_counter 114 Field.creation_counter += 1 116 # Adjust the appropriate creation counter, and save our local copy. 117 if auto_created: 118 self.creation_counter = Field.auto_creation_counter 119 Field.auto_creation_counter -= 1 120 else: 121 self.creation_counter = Field.creation_counter 122 Field.creation_counter += 1 115 123 116 124 def __cmp__(self, other): django/branches/queryset-refactor/django/db/models/fields/related.py
r7096 r7126 495 495 # signature of ManyToOneRel.__init__(). 496 496 super(OneToOneRel, self).__init__(to, field_name, num_in_admin, 497 edit_inline, related_name, limit_choices_to, lookup_overrides, 498 raw_id_admin) 497 edit_inline=edit_inline, related_name=related_name, 498 limit_choices_to=limit_choices_to, 499 lookup_overrides=lookup_overrides, raw_id_admin=raw_id_admin) 499 500 self.multiple = False 500 501 … … 755 756 def save_form_data(self, instance, data): 756 757 setattr(instance, self.attname, data) 757 758 758 759 def formfield(self, **kwargs): 759 760 defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.all()} django/branches/queryset-refactor/django/db/models/manager.py
r7049 r7126 6 6 def ensure_default_manager(sender): 7 7 cls = sender 8 if not hasattr(cls, '_default_manager') :8 if not hasattr(cls, '_default_manager') or cls._default_manager is None: 9 9 # Create the default manager, if needed. 10 10 try: … … 32 32 self.model = model 33 33 setattr(model, name, ManagerDescriptor(self)) 34 if not hasattr(model, '_default_manager') or self.creation_counter < model._default_manager.creation_counter:34 if not hasattr(model, '_default_manager') or model._default_manager is None or self.creation_counter < model._default_manager.creation_counter: 35 35 model._default_manager = self 36 36 django/branches/queryset-refactor/django/db/models/options.py
r7048 r7126 1 import re 2 from bisect import bisect 3 1 4 from django.conf import settings 2 5 from django.db.models.related import RelatedObject … … 8 11 from django.utils.translation import activate, deactivate_all, get_language, string_concat 9 12 from django.utils.encoding import force_unicode, smart_str 10 from bisect import bisect 11 import re 13 from django.utils.datastructures import SortedDict 12 14 13 15 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces". … … 16 18 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 17 19 'unique_together', 'permissions', 'get_latest_by', 18 'order_with_respect_to', 'app_label', 'db_tablespace') 20 'order_with_respect_to', 'app_label', 'db_tablespace', 21 'abstract') 19 22 20 23 class Options(object): 21 24 def __init__(self, meta): 22 self. fields, self.many_to_many = [], []25 self.local_fields, self.local_many_to_many = [], [] 23 26 self.module_name, self.verbose_name = None, None 24 27 self.verbose_name_plural = None … … 36 39 self.has_auto_field, self.auto_field = False, None 37 40 self.one_to_one_field = None 38 self.parents = [] 41 self.abstract = False 42 self.parents = SortedDict() 39 43 40 44 def contribute_to_class(self, cls, name): … … 83 87 84 88 if self.pk is None: 85 auto = AutoField(verbose_name='ID', primary_key=True) 86 auto.creation_counter = -1 87 model.add_to_class('id', auto) 89 if self.parents: 90 # Promote the first parent link in lieu of adding yet another 91 # field. 92 field = self.parents.value_for_index(0) 93 field.primary_key = True 94 self.pk = field 95 else: 96 auto = AutoField(verbose_name='ID', primary_key=True, 97 auto_created=True) 98 model.add_to_class('id', auto) 88 99 89 100 # If the db_table wasn't provided, use the app_label + module_name. … … 98 109 # self.many_to_many. 99 110 if field.rel and isinstance(field.rel, ManyToManyRel): 100 self. many_to_many.insert(bisect(self.many_to_many, field), field)111 self.local_many_to_many.insert(bisect(self.local_many_to_many, field), field) 101 112 else: 102 self. fields.insert(bisect(self.fields, field), field)113 self.local_fields.insert(bisect(self.local_fields, field), field) 103 114 if not self.pk and field.primary_key: 104 115 self.pk = field 105 116 field.serialize = False 117 118 # All of these internal caches need to be updated the next time they 119 # are used. 120 # TODO: Do this more neatly. (Also, use less caches!) 121 if hasattr(self, '_field_cache'): 122 del self._field_cache 123 if hasattr(self, '_m2m_cache'): 124 del self._m2m_cache 125 if hasattr(self, '_name_map'): 126 del self._name_map 106 127 107 128 def __repr__(self): … … 124 145 verbose_name_raw = property(verbose_name_raw) 125 146 147 def _fields(self): 148 """ 149 The getter for self.fields. This returns the list of field objects 150 available to this model (including through parent models). 151 """ 152 try: 153 self._field_cache 154 except AttributeError: 155 self._fill_fields_cache() 156 return self._field_cache.keys() 157 fields = property(_fields) 158 159 def get_fields_with_model(self): 160 """ 161 Returns a list of (field, model) pairs for all fields. The "model" 162 element is None for fields on the current model. Mostly of use when 163 constructing queries so that we know which model a field belongs to. 164 """ 165 try: 166 self._field_cache 167 except AttributeError: 168 self._fill_fields_cache() 169 return self._field_cache.items() 170 171 def _fill_fields_cache(self): 172 cache = SortedDict() 173 for parent in self.parents: 174 for field, model in parent._meta.get_fields_with_model(): 175 if model: 176 cache[field] = model 177 else: 178 cache[field] = parent 179 for field in self.local_fields: 180 cache[field] = None 181 self._field_cache = cache 182 183 def _many_to_many(self): 184 try: 185 self._m2m_cache 186 except AttributeError: 187 self._fill_m2m_cache() 188 return self._m2m_cache.keys() 189 many_to_many = property(_many_to_many) 190 191 def get_m2m_with_model(self): 192 """ 193 The many-to-many version of get_fields_with_model(). 194 """ 195 try: 196 self._m2m_cache 197 except AttributeError: 198 self._fill_m2m_cache() 199 return self._m2m_cache.items() 200 201 def _fill_m2m_cache(self): 202 cache = SortedDict() 203 for parent in self.parents: 204 for field, model in parent._meta.get_m2m_with_model(): 205 if model: 206 cache[field] = model 207 else: 208 cache[field] = parent 209 for field in self.local_many_to_many: 210 cache[field] = None 211 self._m2m_cache = cache 212 126 213 def get_field(self, name, many_to_many=True): 127 "Returns the requested field by name. Raises FieldDoesNotExist on error." 214 """ 215 Returns the requested field by name. Raises FieldDoesNotExist on error. 216 """ 128 217 to_search = many_to_many and (self.fields + self.many_to_many) or self.fields 129 218 for f in to_search: … … 134 223 def get_field_by_name(self, name, only_direct=False): 135 224 """ 136 Returns the (field_object, direct, m2m), where field_object is the 137 Field instance for the given name, direct is True if the field exists 225 Returns the (field_object, model, direct, m2m), where field_object is 226 the Field instance for the given name, model is the model containing 227 this field (None for local fields), direct is True if the field exists 138 228 on this model, and m2m is True for many-to-many relations. When 139 229 'direct' is False, 'field_object' is the corresponding RelatedObject … … 152 242 result = cache.get(name) 153 243 154 if not result or ( not result[1] and only_direct):244 if not result or (only_direct and not result[2]): 155 245 raise FieldDoesNotExist('%s has no field named %r' 156 246 % (self.object_name, name)) … … 174 264 Initialises the field name -> field object mapping. 175 265 """ 176 cache = dict([(f.name, (f, True, False)) for f in self.fields]) 177 for f in self.many_to_many: 178 cache[f.name] = (f, True, True) 179 for f in self.get_all_related_many_to_many_objects(): 180 cache[f.field.related_query_name()] = (f, False, True) 181 for f in self.get_all_related_objects(): 182 cache[f.field.related_query_name()] = (f, False, False) 266 cache = dict([(f.name, (f, m, True, False)) for f, m in 267 self.get_fields_with_model()]) 268 for f, model in self.get_m2m_with_model(): 269 cache[f.name] = (f, model, True, True) 270 for f, model in self.get_all_related_m2m_objects_with_model(): 271 cache[f.field.related_query_name()] = (f, model, False, True) 272 for f, model in self.get_all_related_objects_with_model(): 273 cache[f.field.related_query_name()] = (f, model, False, False) 183 274 if self.order_with_respect_to: 184 cache['_order'] = OrderWrt(), True, False275 cache['_order'] = OrderWrt(), None, True, False 185 276 if app_cache_ready(): 186 277 self._name_map = cache … … 196 287 return 'delete_%s' % self.object_name.lower() 197 288 198 def get_all_related_objects(self): 199 try: # Try the cache first. 200 return self._all_related_objects 201 except AttributeError: 202 rel_objs = [] 203 for klass in get_models(): 204 for f in klass._meta.fields: 205 if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: 206 rel_objs.append(RelatedObject(f.rel.to, klass, f)) 207 self._all_related_objects = rel_objs 208 return rel_objs 289 def get_all_related_objects(self, local_only=False): 290 try: 291 self._related_objects_cache 292 except AttributeError: 293 self._fill_related_objects_cache() 294 if local_only: 295 return [k for k, v in self._related_objects_cache.items() if not v] 296 return self._related_objects_cache.keys() 297 298 def get_all_related_objects_with_model(self): 299 """ 300 Returns a list of (related-object, model) pairs. Similar to 301 get_fields_with_model(). 302 """ 303 try: 304 self._related_objects_cache 305 except AttributeError: 306 self._fill_related_objects_cache() 307 return self._related_objects_cache.items() 308 309 def _fill_related_objects_cache(self): 310 cache = SortedDict() 311 parent_list = self.get_parent_list() 312 for parent in self.parents: 313 for obj, model in parent._meta.get_all_related_objects_with_model(): 314 if obj.field.creation_counter < 0 and obj.model not in parent_list: 315 continue 316 if not model: 317 cache[obj] = parent 318 else: 319 cache[obj] = model 320 for klass in get_models(): 321 for f in klass._meta.local_fields: 322 if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: 323 cache[RelatedObject(f.rel.to, klass, f)] = None 324 self._related_objects_cache = cache 325 326 def get_all_related_many_to_many_objects(self, local_only=False): 327 try: 328 cache = self._related_many_to_many_cache 329 except AttributeError: 330 cache = self._fill_related_many_to_many_cache() 331 if local_only: 332 return [k for k, v in cache.items() if not v] 333 return cache.keys() 334 335 def get_all_related_m2m_objects_with_model(self): 336 """ 337 Returns a list of (related-m2m-object, model) pairs. Similar to 338 get_fields_with_model(). 339 """ 340 try: 341 cache = self._related_many_to_many_cache 342 except AttributeError: 343 cache = self._fill_related_many_to_many_cache() 344 return cache.items() 345 346 def _fill_related_many_to_many_cache(self): 347 cache = SortedDict() 348 parent_list = self.get_parent_list() 349 for parent in self.parents: 350 for obj, model in parent._meta.get_all_related_m2m_objects_with_model(): 351 if obj.field.creation_counter < 0 and obj.model not in parent_list: 352 continue 353 if not model: 354 cache[obj] = parent 355 else: 356 cache[obj] = model 357 for klass in get_models(): 358 for f in klass._meta.local_many_to_many: 359 if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: 360 cache[RelatedObject(f.rel.to, klass, f)] = None 361 if app_cache_ready(): 362 self._related_many_to_many_cache = cache 363 return cache 209 364 210 365 def get_followed_related_objects(self, follow=None): … … 230 385 return follow 231 386 232 def get_all_related_many_to_many_objects(self): 233 try: # Try the cache first. 234 return self._all_related_many_to_many_objects 235 except AttributeError: 236 rel_objs = [] 237 for klass in get_models(): 238 for f in klass._meta.many_to_many: 239 if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: 240 rel_objs.append(RelatedObject(f.rel.to, klass, f)) 241 if app_cache_ready(): 242 self._all_related_many_to_many_objects = rel_objs 243 return rel_objs 387 def get_base_chain(self, model): 388 """ 389 Returns a list of parent classes leading to 'model' (order from closet 390 to most distant ancestor). This has to handle the case were 'model' is 391 a granparent or even more distant relation. 392 """ 393 if not self.parents: 394 return 395 if model in self.parents: 396 return [model] 397 for parent in self.parents: 398 res = parent._meta.get_base_chain(model) 399 if res: 400 res.insert(0, parent) 401 return res 402 raise TypeError('%r is not an ancestor of this model' 403 % model._meta.module_name) 404 405 def get_parent_list(self): 406 """ 407 Returns a list of all the ancestor of this model as a list. Useful for 408 determining if something is an ancestor, regardless of lineage. 409 """ 410 # FIXME: Fix model hashing and then use a Set here. 411 result = [] 412 for parent in self.parents: 413 result.append(parent) 414 result.extend(parent._meta.get_parent_list()) 415 return result 244 416 245 417 def get_ordered_objects(self): django/branches/queryset-refactor/django/db/models/sql/query.py
r7048 r7126 390 390 elif self.default_cols: 391 391 table_alias = self.tables[0] 392 result = ['%s.%s' % (qn(table_alias), qn(f.column)) 393 for f in self.model._meta.fields] 392 root_pk = self.model._meta.pk.column 393 seen = {None: table_alias} 394 for field, model in self.model._meta.get_fields_with_model(): 395 if model not in seen: 396 seen[model] = self.join((table_alias, model._meta.db_table, 397 root_pk, model._meta.pk.column)) 398 result.append('%s.%s' % (qn(seen[model]), qn(field.column))) 394 399 aliases = result[:] 395 400 … … 743 748 alias = self.join((None, opts.db_table, None, None)) 744 749 745 field, target, unused, join_list, = self.setup_joins(parts, opts,750 field, target, opts, join_list, = self.setup_joins(parts, opts, 746 751 alias, (connector == AND)) 747 752 col = target.column … … 851 856 852 857 try: 853 field, direct, m2m = opts.get_field_by_name(name)858 field, model, direct, m2m = opts.get_field_by_name(name) 854 859 except FieldDoesNotExist: 855 860 names = opts.get_all_field_names() 856 861 raise TypeError("Cannot resolve keyword %r into field. " 857 862 "Choices are: %s" % (name, ", ".join(names))) 863 if model: 864 # The field lives on a base class of the current model. 865 alias_list = [] 866 for int_model in opts.get_base_chain(model): 867 lhs_col = opts.parents[int_model].column 868 opts = int_model._meta 869 alias = self.join((alias, opts.db_table, lhs_col, 870 opts.pk.column)) 871 alias_list.append(alias) 872 joins.append(alias_list) 858 873 cached_data = opts._join_cache.get(name) 859 874 orig_opts = opts … … 900 915 joins.append([alias]) 901 916 else: 917 # Non-relation fields. 902 918 target = field 903 919 break … … 1243 1259 from django.db.models.base import Model 1244 1260 for name, val in values.items(): 1245 field, direct, m2m = self.model._meta.get_field_by_name(name)1261 field, model, direct, m2m = self.model._meta.get_field_by_name(name) 1246 1262 if not direct or m2m: 1247 1263 # Can only update non-relation fields and foreign keys. django/branches/queryset-refactor/docs/model-api.txt
r7124 r7126 2029 2029 .. _database API docs: ../db-api/ 2030 2030 2031 Model inheritance 2032 ================= 2033 2034 Abstract base classes 2035 --------------------- 2036 2037 Abstract base classes are useful when you want to put some common information 2038 into a number of other models. You write your base class and put 2039 ``abstract=True`` in the ``Meta`` class
