Skip to content

Instantly share code, notes, and snippets.

@charettes
Last active March 26, 2019 09:33
Show Gist options
  • Save charettes/5670245 to your computer and use it in GitHub Desktop.
Save charettes/5670245 to your computer and use it in GitHub Desktop.
django-mutant use case.

Django mutant use cases

Model creation

Reproducing an existing model setup

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')

Using create() and get_or_create().

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]
)

Using contrib fields.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment