You can extend the class ModifiedModel to set new fields, replace existing or exclude any fields from a model class without patch or change the original code.
my_app/models.py
from django.db import models
class CustomerType(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Customer(models.Model):
name = models.CharField(max_length=50)
type = models.ForeignKey('CustomerType')
is_active = models.BooleanField(default=True, blank=True)
employer = models.CharField(max_length=100)
def __unicode__(self):
return self.name
another_app/models.py
from django.db import models
from django.contrib.auth.models import User
from this_snippet import ModifiedModel
class City(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class HelperCustomerType(ModifiedModel):
class Meta:
model = 'my_app.CustomerType'
description = models.TextField()
class HelperCustomer(ModifiedModel):
class Meta:
model = 'my_app.Customer'
exclude = ('employer',)
type = models.CharField(max_length=50) # Replaced
address = models.CharField(max_length=100)
city = models.ForeignKey(City)
def __unicode__(self):
return '%s - %s'%(self.pk, self.name)
class HelperUser(ModifiedModel):
class Meta:
model = User
website = models.URLField(blank=True, verify_exists=False)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | """
Alert: tested only with revision #15056 in development (never tested in production).
"""
import types
from django.db import models
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model
from django.db.models.fields import FieldDoesNotExist
class ModifiedModelMetaclass(type):
def __new__(cls, name, bases, attrs):
new_class = super(ModifiedModelMetaclass, cls).__new__(cls, name, bases, attrs)
if name == 'ModifiedModel' and bases[0] == object:
return new_class
try:
meta = attrs['Meta']()
except KeyError:
raise ImproperlyConfigured("Helper class %s hasn't a Meta subclass!" % name)
# Find model class for this helper
if isinstance(getattr(meta, 'model', None), basestring):
model_class = get_model(*meta.model.split('.'))
elif issubclass(getattr(meta, 'model', None), models.Model):
model_class = meta.model
else:
raise ImproperlyConfigured("Model informed by Meta subclass of %s is improperly!" % name)
def remove_field(f_name):
# Removes the field form local fields list
model_class._meta.local_fields = [f for f in model_class._meta.local_fields
if f.name != f_name]
# Removes the field setter if exists
if hasattr(model_class, f_name):
delattr(model_class, f_name)
# Removes fields setted in attribute 'exclude'
if isinstance(getattr(meta, 'exclude', None), (list,tuple)):
for f_name in meta.exclude:
remove_field(f_name)
# Calls 'contribute_to_class' from field to sender class
for f_name, field in attrs.items():
if isinstance(field, models.Field):
# Removes the field if it already exists
remove_field(f_name)
# Appends the new field to model class
field.contribute_to_class(model_class, f_name)
# Attaches methods
for m_name, func in attrs.items():
if callable(func) and type(func) == types.FunctionType:
setattr(model_class, m_name, func)
new_class._meta = meta
return new_class
class ModifiedModel(object):
__metaclass__ = ModifiedModelMetaclass
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 3 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 4 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
This is pretty nice, does it work with South?
#
Please login first before commenting.