Ticket #122: meta6.diff

File meta6.diff, 8.2 KB (added by mmarshall, 10 years ago)

Fixed a bug with relationship fields in the 'fields' attribute being duplicated. (oops)

  • django/core/meta.py

     
    393393
    394394class ModelBase(type):
    395395    "Metaclass for all models"
     396   
     397    # We need to keep track of Fields which are initiated inside of the class body, but
     398    # not assined to an attribute.  (These could be ForeignKeys, ManyToManyFields, or
     399    # OneToOneFields.)
     400    _defined_fields_bank = {}
     401   
    396402    def __new__(cls, name, bases, attrs):
    397403        # If this isn't a subclass of Model, don't do anything special.
    398404        if not bases:
    399405            return type.__new__(cls, name, bases, attrs)
    400406
     407        # We must refactor the attributes around a little.  All Field class instances will be given
     408        # names (as needed) and moved to the fields list.  All attributes of the Meta class will
     409        # be moved into the main class attrs.
     410
     411        attrs["fields"] = attrs.has_key("fields") and list(attrs["fields"]) or []
     412
     413        def handle_field(obj, name):
     414            if isinstance(obj, Field):  #Check if this is a field
     415                if isinstance(obj,(ForeignKey, ManyToManyField, OneToOneField)):
     416                    obj.rel.name = name
     417                else:
     418                    obj.set_name(name)
     419                attrs["fields"].append(obj)
     420                return True
     421            else:
     422                return False
     423
     424        # loop through the attributes, and take out the fields.
     425        for key in attrs.keys()[:]:
     426            if handle_field(attrs[key], key):
     427                del attrs[key]  # If the attr was added to fields, we want to delete it.
     428
     429        if attrs.has_key("Meta"):
     430            for name in dir(attrs["Meta"]):
     431                if name.startswith("__"): continue
     432                if name in ("fields",):
     433                    attrs[name].extend( getattr(attrs["Meta"],name) )
     434                else:
     435                    attrs[name] = getattr(attrs["Meta"],name)
     436            del attrs["Meta"]
     437
     438
     439        # We don't want to duplicate relationship keys.
     440        for field in attrs["fields"]:
     441            if ModelBase._defined_fields_bank.has_key(id(field)):
     442                del ModelBase._defined_fields_bank[id(field)]
     443
     444        # Add all of the relationship fields that were not assigned to an attribute. (or
     445        # included in the "fields" attribute in the first place.)
     446        attrs["fields"].extend( ModelBase._defined_fields_bank.values() )
     447        ModelBase._defined_fields_bank = {}
     448
     449        # Sort the fields, so that they appear in the correct order.
     450        attrs["fields"].sort(lambda x,y: x.creation_counter - y.creation_counter)
     451
    401452        # If this model is a subclass of another Model, create an Options
    402453        # object by first copying the base class's _meta and then updating it
    403454        # with the overrides from this class.
     
    15721623    # database level.
    15731624    empty_strings_allowed = True
    15741625
    1575     def __init__(self, name, verbose_name=None, primary_key=False,
     1626    # Will be increased each time a Field object is instanced.  Used to
     1627    # retain the order of fields.
     1628    creation_counter = 0
     1629
     1630    def __init__(self, name=None, verbose_name=None, primary_key=False,
    15761631        maxlength=None, unique=False, blank=False, null=False, db_index=None,
    15771632        core=False, rel=None, default=NOT_PROVIDED, editable=True,
    15781633        prepopulate_from=None, unique_for_date=None, unique_for_month=None,
    15791634        unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
    15801635        help_text=''):
    15811636        self.name = name
    1582         self.verbose_name = verbose_name or name.replace('_', ' ')
     1637        self.original_verbose_name = verbose_name
     1638        self.verbose_name = verbose_name or name and name.replace('_', ' ')
    15831639        self.primary_key = primary_key
    15841640        self.maxlength, self.unique = maxlength, unique
    15851641        self.blank, self.null = blank, null
     
    16041660        else:
    16051661            self.db_index = db_index
    16061662
     1663        # Increase the creation counter, and save our local copy.
     1664        self.creation_counter = Field.creation_counter
     1665        Field.creation_counter += 1
     1666
     1667    def set_name(self, name ):
     1668        """
     1669        Sets the name, and generates the verbose_name from it if needed.
     1670        This function is here for when the name needs to be set later, (such as if it needs to be obtained from
     1671        a the attribute name that stores the Field instance.)
     1672        """
     1673        if not self.original_verbose_name:
     1674            # If the verbose name was originally not specified, we will assume that
     1675            # the user intends for the first argument passed to __init__ to be the verbose_name.
     1676            self.verbose_name = self.name
     1677           
     1678        self.name = name
     1679        self.verbose_name = self.verbose_name or name and name.replace('_', ' ')
     1680           
    16071681    def pre_save(self, obj, value, add):
    16081682        """
    16091683        Hook for altering the object obj based on the value of this field and
     
    17891863
    17901864class DateField(Field):
    17911865    empty_strings_allowed = False
    1792     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs):
     1866    def __init__(self, name=None, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs):
    17931867        self.auto_now, self.auto_now_add = auto_now, auto_now_add
    17941868        if auto_now or auto_now_add:
    17951869            kwargs['editable'] = False
     
    18451919        return [formfields.EmailField]
    18461920
    18471921class FileField(Field):
    1848     def __init__(self, name, verbose_name=None, upload_to='', **kwargs):
     1922    def __init__(self, name=None, verbose_name=None, upload_to='', **kwargs):
    18491923        self.upload_to = upload_to
    18501924        Field.__init__(self, name, verbose_name, **kwargs)
    18511925
     
    19101984
    19111985class FloatField(Field):
    19121986    empty_strings_allowed = False
    1913     def __init__(self, name, verbose_name=None, max_digits=None, decimal_places=None, **kwargs):
     1987    def __init__(self, name=None, verbose_name=None, max_digits=None, decimal_places=None, **kwargs):
    19141988        self.max_digits, self.decimal_places = max_digits, decimal_places
    19151989        Field.__init__(self, name, verbose_name, **kwargs)
    19161990
     
    19922066
    19932067class TimeField(Field):
    19942068    empty_strings_allowed = False
    1995     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs):
     2069    def __init__(self, name=None, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs):
    19962070        self.auto_now, self.auto_now_add  = auto_now, auto_now_add
    19972071        if auto_now or auto_now_add:
    19982072            kwargs['editable'] = False
     
    20192093        return [formfields.TimeField]
    20202094
    20212095class URLField(Field):
    2022     def __init__(self, name, verbose_name=None, verify_exists=True, **kwargs):
     2096    def __init__(self, name=None, verbose_name=None, verify_exists=True, **kwargs):
    20232097        if verify_exists:
    20242098            kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
    20252099        Field.__init__(self, name, verbose_name, **kwargs)
     
    20322106        return [formfields.USStateField]
    20332107
    20342108class XMLField(Field):
    2035     def __init__(self, name, verbose_name=None, schema_path=None, **kwargs):
     2109    def __init__(self, name=None, verbose_name=None, schema_path=None, **kwargs):
    20362110        self.schema_path = schema_path
    20372111        Field.__init__(self, name, verbose_name, **kwargs)
    20382112
     
    20652139            lookup_overrides=kwargs.pop('lookup_overrides', None),
    20662140            raw_id_admin=kwargs.pop('raw_id_admin', False))
    20672141        Field.__init__(self, **kwargs)
     2142        ModelBase._defined_fields_bank[id(self)]=self
    20682143
    20692144    def get_manipulator_field_objs(self):
    20702145        return [formfields.IntegerField]
     
    20802155            filter_interface=kwargs.pop('filter_interface', None),
    20812156            limit_choices_to=kwargs.pop('limit_choices_to', None))
    20822157        Field.__init__(self, **kwargs)
     2158        ModelBase._defined_fields_bank[id(self)]=self
    20832159
    20842160    def get_manipulator_field_objs(self):
    20852161        choices = self.get_choices(include_blank=False)
     
    21052181            raw_id_admin=kwargs.pop('raw_id_admin', False))
    21062182        kwargs['primary_key'] = True
    21072183        IntegerField.__init__(self, **kwargs)
     2184        ModelBase._defined_fields_bank[id(self)]=self
    21082185
    21092186####################
    21102187# RELATIONSHIPS    #
Back to Top