Django model inheritence query - python

Say I have this class in an app:
class Something(models.Model):
pass
But I don't want this class to inherit from models.Model, I want it to inherit from my own custom class, let's call this 'BetterModel'.
Multiple inheritence doesn't work in this situation so I can't do:
import Something
class newClass(Something, BetterModel):
pass
Are there any other options other fork the app?

You can just directly import your parent "BetterModel". As long as better model implements models.Model you should be good.
Additionally, Django does support multiple inheritance of models so you should be able to extend two different classes as long as they extend models.Model.
Additional Resources:
https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance
https://docs.djangoproject.com/en/dev/topics/db/models/#multiple-inheritance

Related

What is the proper way to retrieve all class definitions that contain a specific mixin?

I'm working on a django application, and I want to create a mixin that will always be applied to model definitions. The functionality added by the mixin isn't important for the question.
However, I need to be able to retrieve a list of all the class definitions that inherit from this mixin. These classes can be in different apps within the django project.
Possible answers I've found so far are:
How to find all the subclasses of a class given its name?
How to auto register a class when it's defined
I'm mostly wondering what the best method would be to accomplish this goal.
Typically the way you would get a list of all the classes that inherit a particular class would be by registering the classes with a meta-class (as is explained in one of the questions you have linked). Django models however use their own meta class to achieve a lot of what they do automatically. I wouldn't recommend adding another meta-class into the mix - things could go wrong here!!
Fortunately however, django has something called the content-types framework which is essentially a registry of all of your models in a particular project.
To get a list of all of your models you can do this:
from django.contrib.contenttypes.models import ContentType
content_types = ContentType.objects.all()
This won't get the actual models, but rather a queryset of ContentType instances. To then get the model classes from this you can do
models = [x.model_class() for x in content_types]
So we now have a list of models. Then we can just filter the list down to those models which inherit your mixin:
models_with_mixin = [x for x in models if issubclass(x, MyMixin)]
We can simplify all of the above into the following:
from django.contrib.contenttypes.models import ContentType
models_with_mixin = [
x.model_class()
for x in ContentType.objects.all()
if issubclass(x.model_class(), MyMixin)
]

Recombining multiple inheritance in Django models

Been using Django Polymorphic to help me with complex inheritance patterns in my Django model.
I'm having an issue where I need to have a concrete base model (because it needs to have a ForeignKey to itself), and then have multiple models inherit from it, with eventually some model inheriting from multiple of those. The issue is that I'm getting a E005 error:
app.NamedWeightedModel: (models.E005) The field 'basemodel_ptr' from
parent model 'app.namedmodel' clashes with the field 'basemodel_ptr'
from parent model 'app.massmodel'.
The simple example that triggers this is shown below:
from django.db import models
from polymorphic.models import PolymorphicModel
class BaseModel(PolymorphicModel):
parent = models.ForeignKey('self')
class NamedModel(BaseModel):
name = models.CharField(max_length=32)
class MassModel(BaseModel):
weight = models.FloatField()
class NamedWeightedModel(NamedModel, MassModel):
pass
Is there a better way to handle this? Or a standard approach?
My real model is much more complex (an implementation of the UML spec), and I would like to be able to use multiple inheritance (ideally through Polymorphic) to make things easier.
I've considered making any multiple inheritance models be single inheritance with all additional inherited models mapped as OneToOneFields, but this negates some of the nice things that polymorphic does.
Any help you can provide would be greatly appreciated.

Django: Multiple inheritance from abstract classes with meta

I have a model that inherit from 2 abstract models with attributes in their meta-classes.
How can I make it inherit the metas from both parent classes? It seems like it only inherit the meta of the class written first.
Normal rules for Python's multiple inheritance apply when using it in Django. That means that if multiple parents have the Meta class, only the Meta of the first parent will be used. Others will be ignored.
See this URL for more info
https://docs.djangoproject.com/en/dev/topics/db/models/#multiple-inheritance

Using self in Django Model classes

While adding model class to models.py in Django, why don't we use self with the field variables which we define? Shouldn't not using self field variables make them class variables instead,which "may" cause a problem.
Django uses metaclasses to create the actual class based on the class definition your provide. In brief, upon instantiation of your model class, the metaclass will run through your model field definitions and return a corresponding class with the appropriate attributes.
To answer your question directly, using class variables instead of instance variables (object.self) allows the metaclass to inspect the class attributes without having to first instantiate it.
For more information, have a look at the source and the following docs:
https://code.djangoproject.com/wiki/DynamicModels
https://code.djangoproject.com/wiki/DevModelCreation

Django Model Mixins: inherit from models.Model or from object?

This is a question about Python Mixins that might be useful in general. I'm just using Django models as that is the use-case I'm most familiar with.
Should a mixin inherit from the class it is designed to mix-in with or from 'object'?
Examples by code, what is more correct or better, or better depending on what you want to achieve?
This
class TaggingMixin(models.Model):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
Or this:
class TaggingMixin(object):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
I think inheriting from object is the right way. But I'm seeing examples of the first case all over the net...
EDIT: I've moved my follow up question to a separate question: Django Abstract Models vs simple Python mixins vs Python ABCs
Django does a lot of meta magic when it comes to its model classes, so unfortunately the usual approach to mixins as suggested in Daniel Roseman's answer -- where they inherit from object -- does not work well in the Django universe.
The correct way to structure your mixins, using the example provided, would be:
class TaggingMixin(models.Model):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(TaggingMixin):
title = models.CharField(max_length=100)
Important points here being:
Mixins inherit from model.Model but are configured as an abstract class.
Because mixins inherit from model.Model, your actual model should not inherit from it. If you do, this might trigger a consistent method resolution order exception.
I would recommend that it inherits from object. That way you can ensure that it only provides those methods and attributes you actually define explicitly.
Also, you should always ensure that you put the mixin class first when defining your concrete class. Python's resolution rules mean that the superclasses are searched in order of their definition in the class declaration, and resolution stops when a matching attribute is found. So if your mixin defines a method that is also defined by the main superclass, your mixin method won't be found.
This looks like a job for an abstract model.
EDIT:
Those are not mixins per se. Or rather, they do not need to be. You can derive from an abstract model directly.
When you inherits from plain Python object South doesn't create a migration so you can't use this approach

Categories

Resources