mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refactored metaclass in preparation for descriptor fields
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1701 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -17,7 +17,6 @@ from django.db.models.fields.related import * | |||||||
| from django.core.exceptions import ObjectDoesNotExist | from django.core.exceptions import ObjectDoesNotExist | ||||||
| from django.db.models.exceptions import FieldDoesNotExist, BadKeywordArguments | from django.db.models.exceptions import FieldDoesNotExist, BadKeywordArguments | ||||||
|  |  | ||||||
|  |  | ||||||
| # Admin stages. | # Admin stages. | ||||||
| ADD, CHANGE, BOTH = 1, 2, 3 | ADD, CHANGE, BOTH = 1, 2, 3 | ||||||
|  |  | ||||||
| @@ -28,7 +27,6 @@ ADD, CHANGE, BOTH = 1, 2, 3 | |||||||
| #def get_app(app_label): | #def get_app(app_label): | ||||||
| #    return __import__('%s.%s' % (MODEL_PREFIX, app_label), '', '', ['']) | #    return __import__('%s.%s' % (MODEL_PREFIX, app_label), '', '', ['']) | ||||||
|  |  | ||||||
|  |  | ||||||
| class LazyDate: | class LazyDate: | ||||||
|     """ |     """ | ||||||
|     Use in limit_choices_to to compare the field to dates calculated at run time |     Use in limit_choices_to to compare the field to dates calculated at run time | ||||||
| @@ -50,11 +48,6 @@ class LazyDate: | |||||||
|     def __get_value__(self): |     def __get_value__(self): | ||||||
|         return datetime.datetime.now() + self.delta |         return datetime.datetime.now() + self.delta | ||||||
|  |  | ||||||
| ################ |  | ||||||
| # MAIN CLASSES # |  | ||||||
| ################ |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| from django.db.models.manipulators import ManipulatorDescriptor, ModelAddManipulator, ModelChangeManipulator | from django.db.models.manipulators import ManipulatorDescriptor, ModelAddManipulator, ModelChangeManipulator | ||||||
| from django.db.models.fields import Field, DateField, FileField, ImageField, AutoField | from django.db.models.fields import Field, DateField, FileField, ImageField, AutoField | ||||||
| from django.db.models.fields.related import OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT | from django.db.models.fields.related import RelatedField, OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT | ||||||
| from django.db.models.related import RelatedObject | from django.db.models.related import RelatedObject | ||||||
| from django.db.models.manager import Manager, ManagerDescriptor | from django.db.models.manager import Manager, ManagerDescriptor | ||||||
| from django.db.models.query import orderlist2sql  | from django.db.models.query import orderlist2sql  | ||||||
| @@ -36,22 +36,8 @@ class ModelBase(type): | |||||||
|         except KeyError: |         except KeyError: | ||||||
|             meta_attrs = {} |             meta_attrs = {} | ||||||
|  |  | ||||||
|         # Gather all attributes that are Field or Manager instances. |         # Create the class, because we need it to use in currying. | ||||||
|         fields, managers = [], [] |         new_class = type.__new__(cls, name, bases, { '__module__' : attrs.pop('__module__') }) | ||||||
|         for obj_name, obj in attrs.items(): |  | ||||||
|             if isinstance(obj, Field): |  | ||||||
|                 obj.set_name(obj_name) |  | ||||||
|                 fields.append(obj) |  | ||||||
|                 del attrs[obj_name] |  | ||||||
|             elif isinstance(obj, Manager): |  | ||||||
|                 managers.append((obj_name, obj)) |  | ||||||
|                 del attrs[obj_name] |  | ||||||
|  |  | ||||||
|         # Sort the fields and managers in the order that they were created. The |  | ||||||
|         # "creation_counter" is needed because metaclasses don't preserve the |  | ||||||
|         # attribute order. |  | ||||||
|         fields.sort(lambda x, y: x.creation_counter - y.creation_counter) |  | ||||||
|         managers.sort(lambda x, y: x[1].creation_counter - y[1].creation_counter) |  | ||||||
|          |          | ||||||
|         opts = Options( |         opts = Options( | ||||||
|             module_name = meta_attrs.pop('module_name', get_module_name(name)), |             module_name = meta_attrs.pop('module_name', get_module_name(name)), | ||||||
| @@ -60,7 +46,6 @@ class ModelBase(type): | |||||||
|             verbose_name = meta_attrs.pop('verbose_name', get_verbose_name(name)), |             verbose_name = meta_attrs.pop('verbose_name', get_verbose_name(name)), | ||||||
|             verbose_name_plural = meta_attrs.pop('verbose_name_plural', ''), |             verbose_name_plural = meta_attrs.pop('verbose_name_plural', ''), | ||||||
|             db_table = meta_attrs.pop('db_table', ''), |             db_table = meta_attrs.pop('db_table', ''), | ||||||
|             fields = fields, |  | ||||||
|             ordering = meta_attrs.pop('ordering', None), |             ordering = meta_attrs.pop('ordering', None), | ||||||
|             unique_together = meta_attrs.pop('unique_together', None), |             unique_together = meta_attrs.pop('unique_together', None), | ||||||
|             admin = meta_attrs.pop('admin', None), |             admin = meta_attrs.pop('admin', None), | ||||||
| @@ -76,12 +61,31 @@ class ModelBase(type): | |||||||
|  |  | ||||||
|         if meta_attrs != {}: |         if meta_attrs != {}: | ||||||
|             raise TypeError, "'class META' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()) |             raise TypeError, "'class META' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()) | ||||||
|  |         new_class.add_to_class('_meta', opts) | ||||||
|          |          | ||||||
|         # Create the DoesNotExist exception. |         # Create the DoesNotExist exception. | ||||||
|         attrs['DoesNotExist'] = types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}) |         new_class.DoesNotExist = types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}) | ||||||
|  |          | ||||||
|  |         # Figure out the app_label by looking one level up. | ||||||
|  |         #FIXME: wrong for nested model modules | ||||||
|  |         app_package = sys.modules.get(new_class.__module__) | ||||||
|  |         app_label = app_package.__name__.replace('.models', '') | ||||||
|  |         app_label = app_label[app_label.rfind('.')+1:] | ||||||
|  |  | ||||||
|  |         # Cache the app label. | ||||||
|  |         opts.app_label = app_label | ||||||
|  |          | ||||||
|  |         #Add all attributes to the class | ||||||
|  |         #fields, managers = [], [] | ||||||
|  |         for obj_name, obj in attrs.items(): | ||||||
|  |             new_class.add_to_class(obj_name, obj) | ||||||
|  |          | ||||||
|  |         if not hasattr(new_class, '_default_manager'): | ||||||
|  |             # Create the default manager, if needed. | ||||||
|  |             if hasattr(new_class, 'objects'): | ||||||
|  |                 raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name | ||||||
|  |             new_class.add_to_class('objects',  Manager()) | ||||||
|  |  | ||||||
|         # Create the class, because we need it to use in currying. |  | ||||||
|         new_class = type.__new__(cls, name, bases, attrs) |  | ||||||
|          |          | ||||||
|         # Give the class a docstring -- its definition. |         # Give the class a docstring -- its definition. | ||||||
|         if new_class.__doc__ is None: |         if new_class.__doc__ is None: | ||||||
| @@ -90,41 +94,15 @@ class ModelBase(type): | |||||||
|         if hasattr(new_class, 'get_absolute_url'): |         if hasattr(new_class, 'get_absolute_url'): | ||||||
|             new_class.get_absolute_url = curry(get_absolute_url, opts, new_class.get_absolute_url) |             new_class.get_absolute_url = curry(get_absolute_url, opts, new_class.get_absolute_url) | ||||||
|              |              | ||||||
|         # Figure out the app_label by looking one level up. |         opts._prepare() | ||||||
|         app_package = sys.modules.get(new_class.__module__) |         new_class._prepare() | ||||||
|         app_label = app_package.__name__.replace('.models', '') |  | ||||||
|         app_label = app_label[app_label.rfind('.')+1:] |  | ||||||
|  |  | ||||||
|         # Populate the _MODELS member on the module the class is in. |  | ||||||
|         app_package.__dict__.setdefault('_MODELS', []).append(new_class) |  | ||||||
|  |  | ||||||
|         # Cache the app label. |  | ||||||
|         opts.app_label = app_label |  | ||||||
|          |          | ||||||
|         # If the db_table wasn't provided, use the app_label + module_name. |         # If the db_table wasn't provided, use the app_label + module_name. | ||||||
|         if not opts.db_table: |         if not opts.db_table: | ||||||
|             opts.db_table = "%s_%s" % (app_label, opts.module_name) |             opts.db_table = "%s_%s" % (app_label, opts.module_name) | ||||||
|         new_class._meta = opts |  | ||||||
|          |          | ||||||
|         for m_name, m in managers: |         # Populate the _MODELS member on the module the class is in. | ||||||
|             new_class.add_to_class(m_name, m) |         app_package.__dict__.setdefault('_MODELS', []).append(new_class) | ||||||
|          |  | ||||||
|         if not hasattr(new_class, '_default_manager'): |  | ||||||
|             # Create the default manager, if needed. |  | ||||||
|             if hasattr(new_class, 'objects'): |  | ||||||
|                 raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name |  | ||||||
|             new_class.add_to_class('objects',  Manager()) |  | ||||||
|  |  | ||||||
|         new_class._prepare() |  | ||||||
|  |  | ||||||
|         for field in fields: |  | ||||||
|             if field.rel: |  | ||||||
|                 other = field.rel.to |  | ||||||
|                 if isinstance(other, basestring): |  | ||||||
|                     print "string lookup" |  | ||||||
|                 else: |  | ||||||
|                     related = RelatedObject(other._meta, new_class, field) |  | ||||||
|                     field.contribute_to_related_class(other, related) |  | ||||||
|          |          | ||||||
|      |      | ||||||
|         return new_class |         return new_class | ||||||
| @@ -207,13 +185,6 @@ class Model(object): | |||||||
|                     if not f.height_field: |                     if not f.height_field: | ||||||
|                         setattr(cls, 'get_%s_height' % f.name, curry(cls.__get_FIELD_height, field=f)) |                         setattr(cls, 'get_%s_height' % f.name, curry(cls.__get_FIELD_height, field=f)) | ||||||
|  |  | ||||||
|             # If the object has a relationship to itself, as designated by |  | ||||||
|             # RECURSIVE_RELATIONSHIP_CONSTANT, create that relationship formally. |  | ||||||
|             if f.rel and f.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT: |  | ||||||
|                 f.rel.to = cls |  | ||||||
|                 f.name = f.name or (f.rel.to._meta.object_name.lower() + '_' + f.rel.to._meta.pk.name) |  | ||||||
|                 f.verbose_name = f.verbose_name or f.rel.to._meta.verbose_name |  | ||||||
|                 f.rel.field_name = f.rel.field_name or f.rel.to._meta.pk.name |  | ||||||
|  |  | ||||||
|             # Add methods for many-to-one related objects. |             # Add methods for many-to-one related objects. | ||||||
|             # EXAMPLES: Choice.get_poll(), Story.get_dateline() |             # EXAMPLES: Choice.get_poll(), Story.get_dateline() | ||||||
| @@ -234,6 +205,8 @@ class Model(object): | |||||||
|             cls.get_next_in_order = curry(cls.__get_next_or_previous_in_order, is_next=True) |             cls.get_next_in_order = curry(cls.__get_next_or_previous_in_order, is_next=True) | ||||||
|             cls.get_previous_in_order = curry(cls.__get_next_or_previous_in_order, is_next=False) |             cls.get_previous_in_order = curry(cls.__get_next_or_previous_in_order, is_next=False) | ||||||
|          |          | ||||||
|  |         RelatedField.do_pending_lookups(cls) | ||||||
|  |  | ||||||
|     _prepare = classmethod(_prepare) |     _prepare = classmethod(_prepare) | ||||||
|  |  | ||||||
|     def save(self): |     def save(self): | ||||||
|   | |||||||
| @@ -96,7 +96,8 @@ class Field(object): | |||||||
|         unique_for_year=None, validator_list=None, choices=None, radio_admin=None, |         unique_for_year=None, validator_list=None, choices=None, radio_admin=None, | ||||||
|         help_text='', db_column=None): |         help_text='', db_column=None): | ||||||
|         self.name = name |         self.name = name | ||||||
|         self.verbose_name = verbose_name or (name and name.replace('_', ' ')) |         self.verbose_name = verbose_name  | ||||||
|  |          | ||||||
|         self.primary_key = primary_key |         self.primary_key = primary_key | ||||||
|         self.maxlength, self.unique = maxlength, unique |         self.maxlength, self.unique = maxlength, unique | ||||||
|         self.blank, self.null = blank, null |         self.blank, self.null = blank, null | ||||||
| @@ -112,14 +113,21 @@ class Field(object): | |||||||
|         self.db_column = db_column |         self.db_column = db_column | ||||||
|          |          | ||||||
|         # Set db_index to True if the field has a relationship and doesn't explicitly set db_index. |         # Set db_index to True if the field has a relationship and doesn't explicitly set db_index. | ||||||
|          |  | ||||||
|         self.db_index = db_index |         self.db_index = db_index | ||||||
|  |  | ||||||
|         # Increase the creation counter, and save our local copy. |         # Increase the creation counter, and save our local copy. | ||||||
|         self.creation_counter = Field.creation_counter |         self.creation_counter = Field.creation_counter | ||||||
|         Field.creation_counter += 1 |         Field.creation_counter += 1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def __cmp__(self,other ): | ||||||
|  |         #This is because bisect does not take a comparison function. grrr.  | ||||||
|  |         return cmp(self.creation_counter, other.creation_counter) | ||||||
|  |  | ||||||
|  |     def contribute_to_class(self, cls, name): | ||||||
|  |         self.name = name | ||||||
|         self.attname, self.column = self.get_attname_column() |         self.attname, self.column = self.get_attname_column() | ||||||
|  |         self.verbose_name = self.verbose_name or (name and name.replace('_', ' ')) | ||||||
|  |         cls._meta.add_field(self) | ||||||
|  |  | ||||||
|     def set_name(self, name): |     def set_name(self, name): | ||||||
|         self.name = name |         self.name = name | ||||||
|   | |||||||
| @@ -1,21 +1,63 @@ | |||||||
| from django.db.models.fields import Field, IntegerField | from django.db.models.fields import Field, IntegerField | ||||||
|  | from django.db.models.related import RelatedObject | ||||||
| from django.utils.translation import gettext_lazy, string_concat | from django.utils.translation import gettext_lazy, string_concat | ||||||
| from django.utils.functional import curry | from django.utils.functional import curry | ||||||
| from django.core import formfields | from django.core import formfields | ||||||
|  |  | ||||||
|  |  | ||||||
| # Values for Relation.edit_inline. | # Values for Relation.edit_inline. | ||||||
| TABULAR, STACKED = 1, 2 | TABULAR, STACKED = 1, 2 | ||||||
|  |  | ||||||
| RECURSIVE_RELATIONSHIP_CONSTANT = 'self' | RECURSIVE_RELATIONSHIP_CONSTANT = 'self' | ||||||
|  |  | ||||||
| #HACK  | #HACK  | ||||||
| class SharedMethods(object): | class RelatedField(object): | ||||||
|  |     pending_lookups = {} | ||||||
|  |      | ||||||
|  |     def add_lookup(cls, rel_cls, field): | ||||||
|  |         name = field.rel.to | ||||||
|  |         module = rel_cls.__module__ | ||||||
|  |         key = (module, name) | ||||||
|  |         cls.pending_lookups.setdefault(key,[]).append( (rel_cls, field) ) | ||||||
|  |     add_lookup = classmethod(add_lookup) | ||||||
|  |          | ||||||
|  |     def do_pending_lookups(cls, other_cls): | ||||||
|  |         key = (other_cls.__module__, other_cls.__name__) | ||||||
|  |         for (rel_cls,field) in cls.pending_lookups.setdefault(key,[]): | ||||||
|  |             field.rel.to = other_cls | ||||||
|  |             field.do_related_class(other_cls, rel_cls) | ||||||
|  |     do_pending_lookups = classmethod(do_pending_lookups) | ||||||
|  |      | ||||||
|  |     def contribute_to_class(self, cls, name): | ||||||
|  |         Field.contribute_to_class(self,cls,name) | ||||||
|  |         other = self.rel.to | ||||||
|  |         if isinstance(other, basestring): | ||||||
|  |             if other == RECURSIVE_RELATIONSHIP_CONSTANT: | ||||||
|  |                 self.rel.to = cls.__name__ | ||||||
|  |                 self.add_lookup(cls, self) | ||||||
|  |         else: | ||||||
|  |             self.do_related_class(other, cls) | ||||||
|  |  | ||||||
|  |     def set_attributes_from_rel(self): | ||||||
|  |         self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name) | ||||||
|  |         self.verbose_name = self.verbose_name or self.rel.to._meta.verbose_name | ||||||
|  |         self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name | ||||||
|  |          | ||||||
|  |     def do_related_class(self, other, cls): | ||||||
|  |         self.set_attributes_from_rel() | ||||||
|  |         related = RelatedObject(other._meta, cls, self) | ||||||
|  |         self.contribute_to_related_class(other, related) | ||||||
|  |          | ||||||
|  |  | ||||||
|  | #HACK | ||||||
|  | class SharedMethods(RelatedField): | ||||||
|     def get_attname(self): |     def get_attname(self): | ||||||
|         return '%s_id' % self.name |         return '%s_id' % self.name | ||||||
|      |      | ||||||
|     def get_validator_unique_lookup_type(self): |     def get_validator_unique_lookup_type(self): | ||||||
|         return '%s__%s__exact' % (self.name, self.rel.get_related_field().name) |         return '%s__%s__exact' % (self.name, self.rel.get_related_field().name) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ForeignKey(SharedMethods,Field): | class ForeignKey(SharedMethods,Field): | ||||||
|     empty_strings_allowed = False |     empty_strings_allowed = False | ||||||
|     def __init__(self, to, to_field=None, **kwargs): |     def __init__(self, to, to_field=None, **kwargs): | ||||||
| @@ -98,7 +140,6 @@ class ForeignKey(SharedMethods,Field): | |||||||
|  |  | ||||||
|     def contribute_to_related_class(self, cls, related): |     def contribute_to_related_class(self, cls, related): | ||||||
|         rel_obj_name = related.get_method_name_part() |         rel_obj_name = related.get_method_name_part() | ||||||
|  |  | ||||||
|         # Add "get_thingie" methods for many-to-one related objects. |         # Add "get_thingie" methods for many-to-one related objects. | ||||||
|         # EXAMPLE: Poll.get_choice() |         # EXAMPLE: Poll.get_choice() | ||||||
|         setattr(cls, 'get_%s' % rel_obj_name, curry(cls._get_related, method_name='get_object', rel_class=related.model, rel_field=related.field)) |         setattr(cls, 'get_%s' % rel_obj_name, curry(cls._get_related, method_name='get_object', rel_class=related.model, rel_field=related.field)) | ||||||
| @@ -147,7 +188,7 @@ class OneToOneField(SharedMethods, IntegerField): | |||||||
|                       rel_class=related.model, rel_field=related.field)) |                       rel_class=related.model, rel_field=related.field)) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ManyToManyField(Field): | class ManyToManyField(RelatedField,Field): | ||||||
|     def __init__(self, to, **kwargs): |     def __init__(self, to, **kwargs): | ||||||
|         kwargs['verbose_name'] = kwargs.get('verbose_name', to._meta.verbose_name_plural) |         kwargs['verbose_name'] = kwargs.get('verbose_name', to._meta.verbose_name_plural) | ||||||
|         kwargs['rel'] = ManyToMany(to, kwargs.pop('singular', None), |         kwargs['rel'] = ManyToMany(to, kwargs.pop('singular', None), | ||||||
| @@ -225,6 +266,9 @@ class ManyToManyField(Field): | |||||||
|             func.alters_data = True |             func.alters_data = True | ||||||
|             setattr(cls, 'set_%s' % related.opts.module_name, func) |             setattr(cls, 'set_%s' % related.opts.module_name, func) | ||||||
|  |  | ||||||
|  |     def set_attributes_from_rel(self): | ||||||
|  |         pass | ||||||
|  |  | ||||||
| class ManyToOne: | class ManyToOne: | ||||||
|     def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, |     def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, | ||||||
|         max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, |         max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, | ||||||
|   | |||||||
| @@ -5,19 +5,17 @@ from django.db.models.loading import get_installed_model_modules | |||||||
| from django.db.models.query import orderlist2sql | from django.db.models.query import orderlist2sql | ||||||
| from django.db.models.exceptions import FieldDoesNotExist | from django.db.models.exceptions import FieldDoesNotExist | ||||||
|  |  | ||||||
|  | from bisect import bisect | ||||||
|  |  | ||||||
| class Options: | class Options: | ||||||
|     def __init__(self, module_name='', verbose_name='', verbose_name_plural='', db_table='', |     def __init__(self, module_name='', verbose_name='', verbose_name_plural='', db_table='', | ||||||
|         fields=None, ordering=None, unique_together=None, admin=None, |         ordering=None, unique_together=None, admin=None, | ||||||
|         where_constraints=None, object_name=None, app_label=None, |         where_constraints=None, object_name=None, app_label=None, | ||||||
|         exceptions=None, permissions=None, get_latest_by=None, |         exceptions=None, permissions=None, get_latest_by=None, | ||||||
|         order_with_respect_to=None, module_constants=None): |         order_with_respect_to=None, module_constants=None): | ||||||
|         # Move many-to-many related fields from self.fields into self.many_to_many. |         # Move many-to-many related fields from self.fields into self.many_to_many. | ||||||
|         self.fields, self.many_to_many = [], [] |         self.fields, self.many_to_many = [], [] | ||||||
|         for field in (fields or []): |          | ||||||
|             if field.rel and isinstance(field.rel, ManyToMany): |  | ||||||
|                 self.many_to_many.append(field) |  | ||||||
|             else: |  | ||||||
|                 self.fields.append(field) |  | ||||||
|         self.module_name, self.verbose_name = module_name, verbose_name |         self.module_name, self.verbose_name = module_name, verbose_name | ||||||
|         self.verbose_name_plural = verbose_name_plural or verbose_name + 's' |         self.verbose_name_plural = verbose_name_plural or verbose_name + 's' | ||||||
|         self.db_table = db_table |         self.db_table = db_table | ||||||
| @@ -28,13 +26,21 @@ class Options: | |||||||
|         self.permissions = permissions or [] |         self.permissions = permissions or [] | ||||||
|         self.object_name, self.app_label = object_name, app_label |         self.object_name, self.app_label = object_name, app_label | ||||||
|         self.get_latest_by = get_latest_by |         self.get_latest_by = get_latest_by | ||||||
|         if order_with_respect_to: |         self.order_with_respect_to = order_with_respect_to | ||||||
|  |          | ||||||
|  |         self.module_constants = module_constants or {} | ||||||
|  |         self.admin = admin | ||||||
|  |      | ||||||
|  |     def contribute_to_class(self, cls, name): | ||||||
|  |         self.model = cls | ||||||
|  |         cls._meta = self | ||||||
|  |  | ||||||
|  |     def _prepare(self): | ||||||
|  |         if self.order_with_respect_to: | ||||||
|             self.order_with_respect_to = self.get_field(order_with_respect_to) |             self.order_with_respect_to = self.get_field(order_with_respect_to) | ||||||
|             self.ordering = ('_order',) |             self.ordering = ('_order',) | ||||||
|         else: |         else: | ||||||
|             self.order_with_respect_to = None |             self.order_with_respect_to = None | ||||||
|         self.module_constants = module_constants or {} |  | ||||||
|         self.admin = admin |  | ||||||
|          |          | ||||||
|         # Calculate one_to_one_field. |         # Calculate one_to_one_field. | ||||||
|         self.one_to_one_field = None |         self.one_to_one_field = None | ||||||
| @@ -51,7 +57,9 @@ class Options: | |||||||
|         # If a primary_key field hasn't been specified, add an |         # If a primary_key field hasn't been specified, add an | ||||||
|         # auto-incrementing primary-key ID field automatically. |         # auto-incrementing primary-key ID field automatically. | ||||||
|         if self.pk is None: |         if self.pk is None: | ||||||
|             self.fields.insert(0, AutoField(name='id', verbose_name='ID', primary_key=True)) |             auto = AutoField(verbose_name='ID', primary_key=True) | ||||||
|  |             auto.creation_counter = -1 | ||||||
|  |             self.model.add_to_class('id', auto) | ||||||
|             self.pk = self.fields[0] |             self.pk = self.fields[0] | ||||||
|         # Cache whether this has an AutoField. |         # Cache whether this has an AutoField. | ||||||
|         self.has_auto_field = False |         self.has_auto_field = False | ||||||
| @@ -64,6 +72,15 @@ class Options: | |||||||
|         #HACK |         #HACK | ||||||
|         self.limit_choices_to = {} |         self.limit_choices_to = {} | ||||||
|  |  | ||||||
|  |     def add_field(self, field): | ||||||
|  |         # Insert the fields in the order that they were created. The | ||||||
|  |         # "creation_counter" is needed because metaclasses don't preserve the | ||||||
|  |         # attribute order. | ||||||
|  |         if field.rel and isinstance(field.rel, ManyToMany): | ||||||
|  |             self.many_to_many.insert(bisect(self.many_to_many, field), field) | ||||||
|  |         else: | ||||||
|  |             self.fields.insert(bisect(self.fields,field),field) | ||||||
|  |              | ||||||
|  |  | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return '<Options for %s>' % self.module_name |         return '<Options for %s>' % self.module_name | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user