Django

Code

Ticket #122: meta5.diff

File meta5.diff, 8.1 kB (added by mmarshall, 3 years ago)

Added support for relationship fields not needing to be assigned to an attribute.

  • django/core/meta.py

    old new  
    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                    # We need to delete this Field from the dict, as it was assigned 
     418                    # to an attribute.  (We don't want to add it again later.) 
     419                    del ModelBase._defined_fields_bank[id(obj)] 
     420                else: 
     421                    obj.set_name(name) 
     422                attrs["fields"].append(obj) 
     423                return True 
     424            else: 
     425                return False 
     426 
     427        # loop through the attributes, and take out the fields. 
     428        for key in attrs.keys()[:]: 
     429            if handle_field(attrs[key], key): 
     430                del attrs[key]  # If the attr was added to fields, we want to delete it. 
     431 
     432        # Add all of the relationship fields that were not assigned to an attribute. 
     433        attrs["fields"].extend( ModelBase._defined_fields_bank.values() ) 
     434        ModelBase._defined_fields_bank = {} 
     435 
     436        if attrs.has_key("Meta"): 
     437            for name in dir(attrs["Meta"]): 
     438                if name.startswith("__"): continue 
     439                if name in ("fields",): 
     440                    attrs[name].extend( getattr(attrs["Meta"],name) ) 
     441                else: 
     442                    attrs[name] = getattr(attrs["Meta"],name) 
     443            del attrs["Meta"] 
     444 
     445        # Sort the fields, so that they appear in the correct order. 
     446        attrs["fields"].sort(lambda x,y: x.creation_counter - y.creation_counter) 
     447 
    401448        # If this model is a subclass of another Model, create an Options 
    402449        # object by first copying the base class's _meta and then updating it 
    403450        # with the overrides from this class. 
     
    15721619    # database level. 
    15731620    empty_strings_allowed = True 
    15741621 
    1575     def __init__(self, name, verbose_name=None, primary_key=False, 
     1622    # Will be increased each time a Field object is instanced.  Used to 
     1623    # retain the order of fields. 
     1624    creation_counter = 0 
     1625 
     1626    def __init__(self, name=None, verbose_name=None, primary_key=False, 
    15761627        maxlength=None, unique=False, blank=False, null=False, db_index=None, 
    15771628        core=False, rel=None, default=NOT_PROVIDED, editable=True, 
    15781629        prepopulate_from=None, unique_for_date=None, unique_for_month=None, 
    15791630        unique_for_year=None, validator_list=None, choices=None, radio_admin=None, 
    15801631        help_text=''): 
    15811632        self.name = name 
    1582         self.verbose_name = verbose_name or name.replace('_', ' ') 
     1633        self.original_verbose_name = verbose_name 
     1634        self.verbose_name = verbose_name or name and name.replace('_', ' ') 
    15831635        self.primary_key = primary_key 
    15841636        self.maxlength, self.unique = maxlength, unique 
    15851637        self.blank, self.null = blank, null 
     
    16041656        else: 
    16051657            self.db_index = db_index 
    16061658 
     1659        # Increase the creation counter, and save our local copy. 
     1660        self.creation_counter = Field.creation_counter 
     1661        Field.creation_counter += 1 
     1662 
     1663    def set_name(self, name ): 
     1664        """ 
     1665        Sets the name, and generates the verbose_name from it if needed. 
     1666        This function is here for when the name needs to be set later, (such as if it needs to be obtained from 
     1667        a the attribute name that stores the Field instance.) 
     1668        """ 
     1669        if not self.original_verbose_name: 
     1670            # If the verbose name was originally not specified, we will assume that  
     1671            # the user intends for the first argument passed to __init__ to be the verbose_name. 
     1672            self.verbose_name = self.name 
     1673             
     1674        self.name = name 
     1675        self.verbose_name = self.verbose_name or name and name.replace('_', ' ') 
     1676             
    16071677    def pre_save(self, obj, value, add): 
    16081678        """ 
    16091679        Hook for altering the object obj based on the value of this field and 
     
    17891859 
    17901860class DateField(Field): 
    17911861    empty_strings_allowed = False 
    1792     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
     1862    def __init__(self, name=None, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
    17931863        self.auto_now, self.auto_now_add = auto_now, auto_now_add 
    17941864        if auto_now or auto_now_add: 
    17951865            kwargs['editable'] = False 
     
    18451915        return [formfields.EmailField] 
    18461916 
    18471917class FileField(Field): 
    1848     def __init__(self, name, verbose_name=None, upload_to='', **kwargs): 
     1918    def __init__(self, name=None, verbose_name=None, upload_to='', **kwargs): 
    18491919        self.upload_to = upload_to 
    18501920        Field.__init__(self, name, verbose_name, **kwargs) 
    18511921 
     
    19101980 
    19111981class FloatField(Field): 
    19121982    empty_strings_allowed = False 
    1913     def __init__(self, name, verbose_name=None, max_digits=None, decimal_places=None, **kwargs): 
     1983    def __init__(self, name=None, verbose_name=None, max_digits=None, decimal_places=None, **kwargs): 
    19141984        self.max_digits, self.decimal_places = max_digits, decimal_places 
    19151985        Field.__init__(self, name, verbose_name, **kwargs) 
    19161986 
     
    19922062 
    19932063class TimeField(Field): 
    19942064    empty_strings_allowed = False 
    1995     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
     2065    def __init__(self, name=None, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
    19962066        self.auto_now, self.auto_now_add  = auto_now, auto_now_add 
    19972067        if auto_now or auto_now_add: 
    19982068            kwargs['editable'] = False 
     
    20192089        return [formfields.TimeField] 
    20202090 
    20212091class URLField(Field): 
    2022     def __init__(self, name, verbose_name=None, verify_exists=True, **kwargs): 
     2092    def __init__(self, name=None, verbose_name=None, verify_exists=True, **kwargs): 
    20232093        if verify_exists: 
    20242094            kwargs.setdefault('validator_list', []).append(validators.isExistingURL) 
    20252095        Field.__init__(self, name, verbose_name, **kwargs) 
     
    20322102        return [formfields.USStateField] 
    20332103 
    20342104class XMLField(Field): 
    2035     def __init__(self, name, verbose_name=None, schema_path=None, **kwargs): 
     2105    def __init__(self, name=None, verbose_name=None, schema_path=None, **kwargs): 
    20362106        self.schema_path = schema_path 
    20372107        Field.__init__(self, name, verbose_name, **kwargs) 
    20382108 
     
    20652135            lookup_overrides=kwargs.pop('lookup_overrides', None), 
    20662136            raw_id_admin=kwargs.pop('raw_id_admin', False)) 
    20672137        Field.__init__(self, **kwargs) 
     2138        ModelBase._defined_fields_bank[id(self)]=self 
    20682139 
    20692140    def get_manipulator_field_objs(self): 
    20702141        return [formfields.IntegerField] 
     
    20802151            filter_interface=kwargs.pop('filter_interface', None), 
    20812152            limit_choices_to=kwargs.pop('limit_choices_to', None)) 
    20822153        Field.__init__(self, **kwargs) 
     2154        ModelBase._defined_fields_bank[id(self)]=self 
    20832155 
    20842156    def get_manipulator_field_objs(self): 
    20852157        choices = self.get_choices(include_blank=False) 
     
    21052177            raw_id_admin=kwargs.pop('raw_id_admin', False)) 
    21062178        kwargs['primary_key'] = True 
    21072179        IntegerField.__init__(self, **kwargs) 
     2180        ModelBase._defined_fields_bank[id(self)]=self 
    21082181 
    21092182#################### 
    21102183# RELATIONSHIPS    #