Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django-mutant creating models in django-admin

I started experimenting with django-mutant 0.0.2 (on django 1.4.2), but due to the lack of documentation I got almost nowhere. The way I understood by the project description I could use it to create my models dynamically, so I thought I can wire it with the django-admin interface, so I can create the models and define all it's fields there. I saw some other alternatives like django-eav, dynamo, Will Hardy's dynamic-models, etc. but it sounds like this is the best implementation until now, so I thought I should use this.

I've put this in settings.py:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'south',
    'polymodels',
    'mutant',
    'mutant.contrib.boolean',
    'mutant.contrib.temporal',
    'mutant.contrib.file',
    'mutant.contrib.numeric',
    'mutant.contrib.text',
    'mutant.contrib.web',
    'mutant.contrib.related',
    'dynamodels'   # this is the name of my testapp
)

I opened up the source of django-mutant to figure out what should I do, and I thought it's enough to import the mutant.models.ModelDefinition and mutant.models.FieldDefinition into my admin.py and register them, so I tried this:

from django.contrib import admin

from mutant import models


class ModelDefinitionAdmin(admin.ModelAdmin):
    pass

admin.site.register(models.ModelDefinition, ModelDefinitionAdmin)


class FieldDefinitionAdmin(admin.ModelAdmin):
    pass

admin.site.register(models.FieldDefinition, FieldDefinitionAdmin)

After a syncdb, I got it running, and I got a "mutant" section in my admin interface, inside it a "Models definition" and "Fields". I added a model successfully, although I couldn't specify any appname that is in the list of INSTALLED_APPS. Adding a field failed badly, for it's Model def parameter I did choose the model I created before(it was the only one on the list), and I did choose "Integer field definition" for Content type. Hitting the save button gave me this:

NotImplementedError at /admin/mutant/fielddefinition/add/

No exception supplied
...
...
/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/field/__init__.py in save
        return super(FieldDefinition, self).save(*args, **kwargs) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_polymodels-1.0.1-py2.6.egg/polymodels/models.py in save
        return super(BasePolymorphicModel, self).save(*args, **kwargs) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/model/__init__.py in save
        self.model_def.model_class(force_create=True) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/model/__init__.py in model_class
            model_class = self._create_model_class(existing_model_class) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/model/__init__.py in _create_model_class
        attrs = self.get_model_attrs(existing_model_class) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/model/__init__.py in get_model_attrs
                            for f in self.fielddefinitions.select_subclasses())) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/model/__init__.py in <genexpr>
                            for f in self.fielddefinitions.select_subclasses())) ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/field/__init__.py in field_instance
        cls = self.get_field_class() ...

/home/user/dev/virenvs/dynamicmodels/lib/python2.6/site-packages/django_mutant-0.0.2-py2.6.egg/mutant/models/field/__init__.py in get_field_class
            raise NotImplementedError 

So it may not be the way I should define my fields (or even models?).. On the project's page there is a snippet which subclasses the FieldDefinition class, creating a DateFieldDefinition, if I put that snippet into my models.py and register that class in my admin, I can add any type of fields successfully. Does it mean I have to subclass all field types I want to use to be able to create them in the admin? Are they actually bound to my Model when I create them this way? Is there a working example somewhere to show at least the basics? Sorry this was the shortest version I could came up with, any suggestion would be appreciated.

UPDATE: I made a mistake in specifying the version I was trying, I got the NotImplementedError for the latest dev version(which is also 0.0.2 by the way), but when I tried the real 0.0.2 got from PyPi the same way as the dev, I got a form-error without an error-message, but something failed at validation definitely. So generally I'm not closer to the solution.

UPDATE2: I registered mutant's base field types dynamically in the admin, and I am able now to add/change/delete models and fields with this admin snippet:

from django.contrib import admin

from mutant import models

for field_type in models.FieldDefinitionBase._field_definitions.values():
    attrs = {'model': field_type}
    FieldDefAdmin = type('{0}Admin'.format(field_type.__name__),
                         (admin.ModelAdmin,),
                         attrs)
    admin.site.register(field_type, FieldDefAdmin)


class ModelDefinitionAdmin(admin.ModelAdmin):
    model = models.ModelDefinition

admin.site.register(models.ModelDefinition, ModelDefinitionAdmin)

However when I inspect the actual data in my database from the mysql console for example, my table is not present in the database. There are mutant's tables, and they contain the entries about my model, and my fields, but I thought once the dynamic model class is constructed, it will be also written to the database as it is.

UPDATE3: Actually I was wrong, the table is found in my database, it's just prefixed with "mutant_" so I didn't recognize it's there. Looks like this will be a valid method to work with it, although to make a decent user-friendly interface to operate with it will require more work.

like image 711
andrean Avatar asked Oct 25 '12 14:10

andrean


People also ask

How do I automatically register all models in Django admin?

To automate this process, we can programmatically fetch all the models in the project and register them with the admin interface. Open admin.py file and add this code to it. This will fetch all the models in all apps and registers them with the admin interface.

Is Django admin customizable?

The Django admin is a powerful built-in tool giving you the ability to create, update, and delete objects in your database using a web interface. You can customize the Django admin to do almost anything you want.

Is Django admin used in production?

Django's Admin is amazing. A built-in and fully functional interface that quickly gets in and allows data entry is priceless. Developers can focus on building additional functionality instead of creating dummy interfaces to interact with the database.


1 Answers

Ok, I'm sorry but I'm too busy (and probably way more lazy) to complete a decent app like I said. But to help at least a bit, I have created a dirty blog post about the topic, and added a sample CRUD app for mutant, but beware, it's really really basic, only to demonstrate the first few steps to get up and running.

http://integricho.github.io/2013/07/22/mutant-introduction/

https://github.com/integricho/mutant-sample-app

like image 192
andrean Avatar answered Sep 17 '22 23:09

andrean