I have an abstract model that contains a field type that I would like to override the widget for in the admin view.
Now you can't register abstract models in the admin view so I have had to override the widget for each of the models that inherit from the abstract model. This feels clunky - is there a neater way to do this?
models.py
class MyAbstractModel(Model):
field_with_widget_i_want_to_override = MyFieldType()
class Meta:
abstract = True
class ModelA(MyAbstractModel):
extra_field = AnotherFieldType()
class ModelB(MyAbstractModel):
different_extra_field = ADifferentFieldType()
admin.py
class ModelAAdmin(ModelAdmin):
formfield_overrides = {
MyFieldType: {'widget': MyWidget},
}
class ModelBAdmin(ModelAdmin):
formfield_overrides = {
MyFieldType: {'widget': MyWidget},
}
admin.site.register(ModelA, ModelAAdmin)
admin.site.register(ModelB, ModelBAdmin)
Now my actual project is a bit more complicated so I don't want to combine ModelAdmins when registering the models, There are also many more Models that inherit from the abstract base model so I feel like I'm repeating myself alot.
Alternatively is there a way to globally overide the widget used in the admin for a field type (for all models)?
Abstract models can't be registered as ModelAdmin as they are abstract and django can't treat them as data models so most of admin functionalities can't be applied on these classes- so you need to override it with an empty class at least like at documentation here
Abstract classes
There's no way to assign data to abstract models
Related
In Django, is there a way to combine two models that inherit the same class into one serializer?
from django.db.models import Model
class A(Model):
a = IntegerField(...)
# other fields...
class Meta:
abstract = True
class B(A):
# There may or may not be such a thing as class C.
class C(A):
# There may or may not be such a thing as class B.
I have code like above.
Could it be possible to create a serializer based on the class A model?
I tried to create a view table in SQL, but gave up due to performance issues.
Any good ideas please. It's so painful...😥
In general it is not a good idea to reuse serializes because doing so may expose you to unexpected behavior, when something changes in the base serializer or when you add/remove attributes to one of your models.
If model B and C have some attributes in common, then perhaps, you should consider changing your DB design.
However, in this case I would define 2 serializes that have the attribute of the abstract model:
class BSerializer(serializers.Serializer):
a = serialzier.IntegerField()
...
class CSerializer(serialziers.Serializer):
a = serializer.IntegerField()
...
I want to create base model for my submodels, for example: Car(Base) and Truck, Sportcart etc. And I want to bind them all using base class with another class, cuz I don't want to bind all of them separately with another class.
Example:
I have a user and I want to add to him cars (I will do it separately for each class, yes). And I want to get all of them using my base Car class.
Mark your base model as abstract:
class Car(models.Model):
# Your fields
class Meta:
abstract = True
Then inherit from the abstract model:
class SportCar(Car):
# Your fields
pass
In this case Django will make migrations only for SportCar, because Car is an abstract model.
I we have this models in django:
class FotherModel(models.Model):
# Some fields goes here!
class Meta:
# Some fields goes here!
abstract = True
class ChildModel(FotherModel):
# Some fields goes here!
class Meta(FotherModel.Meta):
#s Some fields goes here!
When we inherit a field from the meta class of Django models, that field appears in child meta class, But this rule does not apply to abstract=True.
I know that if this happens, no table in database will be created, But I don't know how this inheritance didn't happen. Please explain this process for me.
The Model metaclass resets abstract in a model's Meta class. In this document you can see:
Django does make one adjustment to the Meta class of an abstract base
class: before installing the Meta attribute, it sets abstract=False.
This means that children of abstract base classes don’t automatically
become abstract classes themselves.
Also, you can see the source code of this process in this link:
if abstract:
# Abstract base models can't be instantiated and don't appear in
# the list of models for an app. We do the final setup for them a
# little differently from normal models.
attr_meta.abstract = False
new_class.Meta = attr_meta
return new_class
Because of the concept and effect of some fields in meta section in many cases it doesn't make sense that the field is inherited by chidren.
It has been described here
So I have a base abstract model class
class AbstractBase(models.Model):
category = models.CharField()
// Some fields
class Meta:
abstract = True
Now many classes inherit from this Base. Each category has its own fields
class Category1(AbstractBase):
//some code
class Category2(AbstractBase):
//some code
.
.
.
class CategoryN(AbstractBase):
//some code
Now I do not wish to create separate inlines etc for each of these models.
This is because in the admin only one of these models need to be displayed depending on which category it is.
class CategoryAdminInLine(nested.NestedTabularInline):
model = Category
fields = //some common fields
Is there any easy way to do it?
Try the package django-polymorphic https://github.com/django-polymorphic/django-polymorphic
It adds transparent admin and QuerySet integration for inherited models.
Another solution is to simply remove the abstract=True from the base class.
However, I'm afraid this may not be the right way to do it as it may be copying and duplicating the tables and stuff but works great if the tables won't get too big!..
According to how it's done here.. https://godjango.com/blog/django-abstract-base-class-multi-table-inheritance/
If a django model is made abstract, like below, is there a way to inspect the class to determine that it is abstract?
class MyModel(models.Model):
class Meta:
abstract = True
I would expect that I could examine MyModel.Meta.abstract, but according to Django docs:
Django does make one adjustment to the Meta class of an abstract base class: before installing the Meta attribute, it sets abstract=False. This means that children of abstract base classes don't automatically become abstract classes themselves.
Any ideas? Thanks!
You can instantiate MyModel and then check ._meta.abstract.
So in code:
m = MyModel()
print m._meta.abstract
I'd like to point out that you don't need to instantiate a model to check if it's abstract - Django models inherit an actual metaclass that adds _meta on class instantiation.
So, similarly to #sheats's code, try
from django.db.models import Model
class MyModel(Model):
pass
print MyModel._meta.abstract
Or, for a positive example
from django.db.models import Model
class MyModel(Model):
class Meta(object):
abstract = True
print MyModel._meta.abstract
Of course, this also works for built-in models and anything inheriting from Django's Model.
from django.contrib.auth.models import User
print User._meta.abstract