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
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 have a model set up that is
class BasePage(Page):
class Meta:
abstract = True
class PageTypeA(BasePage):
...
class PageTypeB(BasePage):
...
class PageTypeC(BasePage):
...
etc..
How do I create a query to list all of the pages that inherit from BasePage?
If i am understand you properly you need a parent model that have some generic information and other child models need some extra additional information. You can try third-party django-polymorphic link for that. One of important feature that it support Django-Rest-Framework serializer too.
I'm using Python 3.6+PostgreSQL 10+latest Django and DjangoRestFRamework. I have the following models, in which several models inherit from a class which is the ForeignKey (One-to-Many) of another class.
class Voteable(models.Model):
Voteable_id = models.BigAutoField(primary_key=True);
class base(Voteable):
class Meta:
abstract = False
class traslated_info(models.Model):
info_about=models.ForeignKey(base)
info_body=models.TextField()
info_language=models.CharField(max_length=2)
class A(base):
A_id=models.BigAutoField(primary_key=True)
A_field=models.TextField()
class B(base):
B_id=models.BigAutoField(primary_key=True)
B_field=models.TextField()
B_belongs_to=models.ForeignKey(A)
class C(base):
C_id=models.BigAutoField(primary_key=True)
C_field=models.TextField()
C_belongs_to=models.ForeignKey(A)
C_belongs_to=models.ForeignKey(B)
Whenever I try saving an object A (via curl), django says that base_ptr is required. I don't know how to model this situation. The end user is not expected to create item base and then item A, B or C. I tried class base as abstract, but an abstract class can't be ForeignKey. I want to automatically create a base class whenever a class A is created.
I think I have two options: A) Remove the ForeignKey and store the language-specific info fields as HStoreField. This makes the code somewhate dependent on Postgree. B) Create some sort of routine that automatically creates parent base item whenever a child A item is created (preserving the one to one relationship).
What do you recommend? Is there some django easy option I'm missing to make option B? I have not found this. Thank you.
Having an autofield as primary_key in the models A, B or C causes this error, as creating a child model doesn't cascade-create parents.
I found two workarounds:
Change autofield option primary_key to false and add
SILENCED_SYSTEM_CHECKS=['fields.E100']
Overriding Viewset create method:
#transaction.atomic
def create(self,request,*args,**kwargs):
request.data['base_ptr'] = base.objects.create(user=request.user,created_date=datetime.utcnow()).pk
return super(viewsets.ModelViewSet,self).create(request,*args,**kwargs)
I will stick with the second, I'm quite sure more issues will arise.
Make your serializer as below, you dont need to create base classes explicitly, it will be created automatically.
class ASerializer(serializers.ModelSerializer):
class Meta:
model = A
read_only_fields = ('base_ptr',)
fields = '__all__'
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/
I want to get a derived modelclass instance from an instanciated base modelclass.
I have the following model class hierarchy:
class AlfrescoPFCModel(models.Model):
#some fields and methods
class Meta:
abstract = True
class Contenido(AlfrescoPFCModel):
#some fields and methods
class Proyecto(Contenido):
#some fields and methods
class ProyectoCalificado(Proyecto):
#some fields and methods
class ProyectoArchivado(ProyectoCalificado):
#some fields and methods
And I instantiate a Proyecto class in this way:
proyecto = proyecto_form.save(commit=False)
#do some stuff with some fields that dont appear on the form
proyecto.save
In another view I try to access the derived class ProyectoCalificado from the base class Proyecto previously instanciated and saved in the database doing:
pc = ProyectoCalificado.objects.get(pk=id)
and i get: ProyectoCalificado matching query does not exist.
I also tried:
p = get_object_or_404(Proyecto, id=id)
pc = p.proyectocalificado
but it get the same error in the second line.
Reading the documentation i should be allowed to do that:
#multi-table-inheritance
What i want to do is to incrementally complete the data associated to a Proyecto (project) following this workflow: Proyecto -> ProyectoCalificado -> ProyectoArchivado.
I have 3 different forms for each step. I need 3 different models because I need to save them in the database without filling all the mandatory fields at once.
Thanks!
Use Form Wizards (https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/).
UPDATE
If you can't use Form Wizards because of the situation you describe, then you should make the models fields blank or nullable at the database level and then only enforce field requirements on each individual form. Creating three levels of inheritance solely for the purpose of the single-time set of forms required to create it is absolutely the wrong approach. It only fragments your data across additional tables and makes querying more complicated with no long-term benefit.
So, for example. Set the model itself up as though nothing (or only the items in the first form) are required. Then, in your first form, only make the fields necessary for that particular stage required. You can do this easily by overriding the __init__:
class FirstForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(FirstForm, self).__init__(*args, **kwargs)
self.fields['some_required_field'].required = True
# rinse and repeat
Do the same in your second and third forms, again making on the actual fields that are required for that particular form, required.
Then, call it day and have a drink.
If you have the child instance, it should have a <base class name>_ptr member which points to the instance of its superclass. You can use this as the basis of a filter query to retrieve the child.
You can also just assume that instances of the base and derived class will have the same id if you haven't done anything to affect how ids are allocated.