forked from apluslms/a-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
55 lines (41 loc) · 1.94 KB
/
Copy pathmodels.py
File metadata and controls
55 lines (41 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from django.contrib.contenttypes.models import ContentType
from django.db import models
from model_utils.managers import InheritanceManager
class ModelWithInheritanceManager(InheritanceManager):
def get_queryset(self):
return super().get_queryset().select_related('content_type').select_subclasses()
class ModelWithInheritance(models.Model):
"""
BaseExercise is the base class for all exercise types.
It contains fields that are shared among all types.
"""
objects = ModelWithInheritanceManager()
content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE,
editable=False,
null=True)
class Meta:
abstract = False
def save(self, *args, update_fields=None, **kwargs):
"""
Overrides the default save method from Django. If the method is called for
a new model, its content type will be saved in the database as well. This way
it is possible to later determine if the model is an instance of the
class itself or some of its subclasses.
"""
if not self.content_type:
self.content_type = ContentType.objects.get_for_model(self.__class__)
if update_fields is not None:
update_fields = tuple(set(update_fields) | {"content_type"})
return super().save(*args, update_fields=update_fields, **kwargs)
def as_leaf_class(self):
"""
Checks if the object is an instance of a certain class or one of its subclasses.
If the instance belongs to a subclass, it will be returned as an instance of
that class.
"""
content_type = self.content_type
model_class = content_type.model_class()
if (model_class == self.__class__):
return self
return model_class.objects.get(id=self.id)