The following model setup:
class City(models.Model):
name = models.CharField(max_length=50)
class Meta:
app_label = 'locations'
class Street(models.Model):
name = models.CharField(max_length=50)
city = models.ForeignKey(City)
class Meta:
app_label = 'locations'
Can be reproduced doing the following:
# Create the table and the model
city_model_def = ModelDefinition.objects.create(
app_label='locations', object_name='City'
)
# Add a column to the table and update the model
CharFieldDefinition.objects.create(
model_def=city_model_def, name='name', max_length=50
)
# Create the second table and model
street_model_def = ModelDefinition.objects.create(
app_label='locations', object_name='Street'
)
# Add the columns
CharFieldDefinition.objects.create(
model_def=street_model_def, name='name', max_length=50
)
ForeignKeyDefinition.objects.create(
model_def=street_model_def, name='city', to=city_model_def
)
# Now you can retreive model class from definitions
City = city_model_def.model_class()
Street = street_model_def.model_class()
montreal = City.objects.create(name='Montréal')
papineau = Street.objects.create(city=montreal, name='Papineau')
Adding fields after model creation issues extra ALTER
statements.
For example the following code:
model_def = ModelDefinition.objects.create(
app_label='app', object_name='Model'
)
CharFieldDefinition.objects.create(
model_def=model_def, name='field', max_length=50
)
Would issue the following SQL:
CREATE TABLE app_model { ... };
ALTER TABLE app_model ADD COLUMN name ...;
To include the field
in table creation you can use the fields
kwarg of the create
or get_or_create
method of the ModelDefinitionManager
:
field = CharFieldDefinition(name='field', max_length=50)
ModelDefinition.objects.create(
app_label='app', object_name='Model', fields=[field]
)
Mutant comes bundled with FieldDefinition
associated with all the database fields that comes with Django.
For example, the django.contrib.gis
field definitions can be found in the mutant.contrib.geo
app:
from mutant.contrib.geo.models import GeoModel, PointFieldDefinition
from mutant.models import BaseDefinition, ModelDefinition
ModelDefinition.objects.create(
app_label='myapp',
object_name='MyModel',
bases=[BaseDefinition(base=GeoModel)],
fields=[PointFieldDefinition(name='point')]
)
Note that here we use GeoModel
as an abstract base to inherit its GeoManager
.