views:

756

answers:

2

How add custom field dynamicly? I'm trying that, but the field won't insert into database when I sync db:

#It use as register(MyModel)
def register(model, attr="my_attr"):

    if model in registry:
        raise AlreadyRegistered(
            _('The model %s has already been registered.') % model.__name__)

    registry.append(model)
    setattr(model, attr, MyField())

    MyField().contribute_to_class(model, attr) 

#MyField.contribute_to_class
def contribute_to_class(self, cls, name):
     super(MyField, self).contribute_to_class(cls, name)

     setattr(cls, self.name, self)
     cls.add_to_class('%s_manager' %  name, MyDescriptor())

     signals.post_save.connect(self._save, cls, True)
+2  A: 

You probably cannot do that without hacking into Django's internals. The syncdb command inspects the meta object for each model to get a list of fields to create, which is created on class construction time via the metaclass of the django.db.models.Model base class:

class MyModel(models.Model):
    my_filed = models.CharField(...)

# Here, class construction is complete and your class has a _meta member.
# If you want, you can check it out in the interactive shell.
meta = MyModel._meta

After the class construction is complete, e.g. after the DEDENT following the class statement, the meta object is fixed (not affected by modifying the model class) and you will have to hack the meta (which is of course possible) in order to add dynamic fields. But since you are messing with internal objects here, it could render your app incompatible with future releases of Django.

The remaining question is: Why would you want to do that? Since database tables are usually only created once when deploying your app, models are kind of "static".

Ferdinand Beyer
+1 for referencing the django metaclass. It is possible to write your own model metaclass, as a subclass of django's model metaclass, to do this... in fact, this was the way to get around the lack of model inheritance in the past. Now we have true model inheritance, that's probably a better way.
Jarret Hardie
A: 

I was looking for the same thing and had to settle for raw SQL. Although you can use something like SQLAlchemy.

Sidmitra