django abstract models versus regular inheritance
Django will only generate tables for subclasses ofI actually want to know the difference between a model class that
inherits from a django abstract class (Meta: abstract = True) and a
plain Python class that inherits from say, 'object' (and not
models.Model).
models.Model
, so the former...class User(models.Model):
first_name = models.CharField(max_length=255)
def get_username(self):
return self.username
class Meta:
abstract = True
class Employee(User):
title = models.CharField(max_length=255)
...will cause a single table to be generated, along the lines of...CREATE TABLE myapp_employee
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
...whereas the latter...class User(object):
first_name = models.CharField(max_length=255)
def get_username(self):
return self.username
class Employee(User):
title = models.CharField(max_length=255)
...won't cause any tables to be generated. You could use multiple inheritance to do something like this...
class User(object):
first_name = models.CharField(max_length=255)
def get_username(self):
return self.username
class Employee(User, models.Model):
title = models.CharField(max_length=255)
...which would create a table, but it will ignore the fields defined in the User
class, so you'll end up with a table like this...CREATE TABLE myapp_employee
(
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
Django absract vs non-abstract model inheritance
You might consider generic relations here.
class Annotation(models.Model):
body = models.TextField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
annotated_object = GenericForeignKey('content_type', 'object_id')
class Book(models.Model):
...
annotations = GenericRelation('Annotation')
class Article(models.Model):
...
annotations = GenericRelation('Annotation')
now you can set annotation.annotated_object
to any book or article instance, and in reverse do obj.annotations
from both book and article objects. Why Abstract=True dosen't inherit in Meta class of django model
The Model metaclass resets abstract
in a model's Meta class. In this document you can see:
Also, you can see the source code of this process in this link: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.
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
Django models: Inherit from variable abstract base class
No you can't do this. Django models can't be modified like this during runtime (after django is intialized). Anyway, this is not a good design pattern. You're confusing composition and inheritance. A Transaction
is not a type of Fee
or a type of Order
so it makes no sense to subclass like this.
You can solve your problem without a generic foreign key by just using two separate ForeignKey fields:
class Transactions(models.Model):
transaction_number = models.IntegerField()
order = models.ForeignKey(Orders, null=True, blank=True)
fee = models.ForeignKey(Fees, null=True, blank=True)
You can then query the different transaction types like this:fee_payments = Transactions.objects.exclude(fee=None)
order_payments = Transaction.objects.exclude(order=None)
Is it OK to use multiple inheritance with Django abstract models?
Sounds like for what you're trying to do, mixins really are the best fit. A simple google search will find lots of articles on implementing mixins in python, such as this one. I'm not sure multiple inheritance is the best way to go about doing it, so you might want to explore all the other options. What else have you thought about?
Django model abstract model with constrains not being inherited: 'constraints' refers to field 'xxx' which is not local to model 'Foo'
1. You can't use GenericForeignKey
in UniqueConstraint
, because a GenericForeignKey isn’t a normal field object. Instead in UniqueConstraint
use content_type
and object_id
, this is equivalent to content_object
:
class Meta:
abstract = True
constraints = [
models.UniqueConstraint(
fields=['content_type', 'object_id', 'user'],
name="%(app_label)s_%(class)s_user_unique"),
]
See Django Docs:Due to the way2. According to Django Docs in abstract base classesGenericForeignKey
is implemented, you cannot use
such fields directly with filters (filter() and exclude(), for
example) via the database API. Because aGenericForeignKey
isn’t a normal field object.Likewise,
GenericForeignKey
does not appear in ModelForms.
related_name
must contain '%(app_label)s' and '%(class)s'. And you should always specify a unique reverse name and query name for the field.content_type = models.ForeignKey(
ContentType, on_delete=models.CASCADE,
related_name='%(app_label)s_%(class)s_content_types',
related_query_name='%(app_label)s_%(class)s_content_type',
)
user = models.ForeignKey(
User, blank=False, null=False,
on_delete=models.CASCADE,
related_name='%(app_label)s_%(class)s_users',
related_query_name='%(app_label)s_%(class)s_user',
)
If you are using related_name or related_query_name on a
ForeignKey or ManyToManyField, you must always specify a unique reverse name and query name for the field. This would normally
cause a problem in abstract base classes, since the fields on this
class are included into each of the child classes, with exactly the
same values for the attributes (including related_name and
related_query_name) each time.To work around this problem, when you are using related_name or
related_query_name in an abstract base class (only), part of the value
should contain '%(app_label)s' and '%(class)s'.
Django, a model class which inherits abstract model class can be also abstract?
Yes!
Of course, you can make an abstract base class that inherits from another abstract base class. You just need to remember to explicitly set abstract=True each time.Models | Django Documentation
Updated links for 2.2 and 3.0
Related Topics
Row-Wise Average for a Subset of Columns with Missing Values
How to Implement SQL Coalesce in Pandas
How to Handle Exceptions in a List Comprehensions
How to Plot Only a Table in Matplotlib
Pandas: Subindexing Dataframes: Copies VS Views
Splitting List Based on Missing Numbers in a Sequence
How to Flatten a Pandas Dataframe with Some Columns as JSON
Why Results of Map() and List Comprehension Are Different
Comparable Classes in Python 3
How to Download a File from Google Drive Using Python and the Drive API V3
Make Part of a Matplotlib Title Bold and a Different Color
Passing Double Quote Shell Commands in Python to Subprocess.Popen()
Pd.Timestamp Versus Np.Datetime64: Are They Interchangeable for Selected Uses
Display Realtime Output of a Subprocess in a Tkinter Widget
Can You Make Multiple "If" Conditions in Python