Reputation: 1911
I'd like to add at runtime methods to my django model, so that it's viewable via the admin-interface. Sense: the user should be able to add an CalculationRule and a "virtual" table occurs with the applied rule.
# model.py
from django.db import models
import types
def rule(self):
return 12 * self.calorific_requirement
class BuildingTable(models.Model):
building_nr = models.IntegerField()
square_meter = models.FloatField()
calorific_requirement = models.FloatField()
@staticmethod
def __new__(cls, *args, **kwargs):
setattr(cls, "rule", types.MethodType(rule, cls))
return models.Model.__new__(cls, *args, **kwargs)
def reqirement_per_m2(self): # this is also a rule!
return self.calorific_requirement / self.square_meter
def __unicode__(self):
return "Building " + str(self.building_nr)
class CalculationRule(models.Model):
name = models.CharField(max_length=200)
rule = models.CharField(max_length=200)
def __unicode__(self):
return str(self.name)
But if I add "rule" to my admin.py
it raises BuldingTableAdmin.list_display[4], 'rule' is not a callable or an attribute of 'BuldingTableAdmin' or found in the model 'BuildingTable'.
# admin.py
from calccols_app.models import BuildingTable, CalculationRule
from django.contrib import admin
class BuldingTableAdmin(admin.ModelAdmin):
list_display = ["building_nr", "square_meter", "calorific_requirement", "reqirement_per_m2", "rule"]
admin.site.register(BuildingTable, BuldingTableAdmin)
admin.site.register(CalculationRule)
I've tested BuildingTable
in django's shell; the rule
-method exists, but doesn't work properly. Any ideas how I can inject methods, so that django can handle/register them?
Upvotes: 1
Views: 687
Reputation: 27611
You do not need to create fields in your model to display it in the admin. You can do it in ModelAdmin entity.
class UserAdmin(admin.ModelAdmin):
list_display = ['username', 'fullname']
def fullname(self, model):
return model.first_name + " " + model.second_name
Although we can add a method to your model dynamically. But you must take it as a method, not a property:
def _status(invite):
if invite.is_activated:
return "Activated"
if invite.is_alive:
return "Live"
return "Expired"
_status.short_description = 'status'
Invite.status = _status # Invite is model class
This "property" is normally displayed in the admin and Django-templates.
Upvotes: 1