I'm writing my first Django app. I have the following database model:
class Person(models.Model):
first_name = models.CharField(max_length = 100)
last_name = models.CharField(max_length = 100)
class InformationType(models.Model):
name = models.CharField(max_length = 100)
class Information(models.Model):
person = models.ForeignKey(Person)
info_type = models.ForeignKey(InformationType)
info = models.CharField(max_length = 200)
I want to create multiple inlines in Django Admin (class PersonAdmin(ModelAdmin)) by splitting Information model by types and do it dynamically. Also I want to hide (exclude) field 'info_type' from user interface and automatically fill it with corresponding value.
I can dynamically create inlines with 'Information' data filtered by 'info_type' but hiding this field in UI makes it empty on saving.
How can I do it? Is it possible to make hidden field? Or where i should store 'info_type' value?
I've googled hard and found nothing =)
Appended: OK. I've modified 'Information' class:
class Information(models.Model):
def save(self, *args, **kwargs):
self.info_type = self.fixed_info_type
super(Information, self).save(*args, **kwargs)
... and maked few proxies:
class InformationManager(models.Manager):
def __init__(self, info_type, *args, **kwargs):
self.__info_type = info_type
super(InformationManager, self).__init__(*args, **kwargs)
def get_query_set(self, *args, **kwargs):
return super(self.__class__, self).get_query_set(*args, **kwargs).filter(info_type=self.__info_type)
class PhoneInformation(Information):
fixed_info_type = 'PHONE'
objects = InformationManager(fixed_info_type)
class Meta:
proxy = True
class EmailInformation(Information):
fixed_info_type = 'EMAIL'
objects = InformationManager(fixed_info_type)
class Meta:
proxy = True
in admin.py:
from contacts.models import Person, PhoneInformation, EmailInformation
class PersonAdmin(admin.ModelAdmin):
__inlines = []
class classproperty(property):
def __get__(self, instance, owner):
return super(self.__class__, self).fget.__get__(None, owner)()
@classproperty
@classmethod
def inlines(cls):
def get_inline(InformationModel):
class Inline(admin.TabularInline):
model = InformationModel
exclude= ['info_type']
return Inline
if not cls.__inlines:
for InformationModel in [PhoneInformation, EmailInformation]:
cls.__inlines.append(get_inline(InformationModel))
return cls.__inlines
So it looks ugly and don't conform to DRY principles. I can't create proxies the same way as InlineAdmin. It gets back the same object each time.
I've found solution. Now I can create dynamic proxy models on the fly. models.py:
class Person(models.Model):
first_name = models.CharField(max_length = 100)
last_name = models.CharField(max_length = 100)
class InformationType(models.Model):
class Meta:
ordering = ['order']
name = models.CharField(max_length = 200)
order = models.IntegerField()
class Information(models.Model):
person = models.ForeignKey(Person)
info_type = models.ForeignKey(InformationType)
value = models.CharField(max_length = 200)
@classmethod
def getProxy(cls, info_type):
class InformationManager(models.Manager):
def get_query_set(self, *args, **kwargs):
return super(self.__class__, self).get_query_set(*args, **kwargs).filter(info_type = info_type)
def save(self, *args, **kwargs):
self.info_type = info_type
super(Information, self).save(*args, **kwargs)
class Meta:
proxy = True
return type(
'Information'+str(info_type.pk),
(Information,),
{
'Meta': Meta,
'save': save,
'__module__': 'contacts.models',
'objects': InformationManager(),
}
)
in admin.py:
class PersonAdmin(admin.ModelAdmin):
__inlines = []
class classproperty(property):
def __get__(self, instance, owner):
return super(self.__class__, self).fget.__get__(None, owner)()
@classproperty
@classmethod
def inlines(cls):
def get_inline(info_model):
class Inline(admin.TabularInline):
model = info_model
exclude= ['info_type']
return Inline
if not cls.__inlines:
for info_model in [Information.getProxy(info_type) for info_type in InformationType.objects.all()]:
cls.__inlines.append(get_inline(info_model))
return cls.__inlines
Something I've done in the past is:
Create your various inline forms, overriding the queryset for each to only allow specific subsets of the Information by Type
(Look at this for inspiration: Limit the queryset of entries displayed for a django admin Inline)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With