This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
new_class._prepare() | |
new_class._meta.apps.register_model(new_class._meta.app_label, new_class) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# stolen from https://stackoverflow.com/questions/16655097/django-abstract-models-versus-regular-inheritance | |
class PermissionsMixin(models.Model): | |
""" | |
A mixin class that adds the fields and methods necessary to support | |
Django's Group and Permission model using the ModelBackend. | |
""" | |
is_superuser = models.BooleanField(_('superuser status'), default=False, | |
help_text=_('Designates that this user has all permissions without ' | |
'explicitly assigning them.')) | |
groups = models.ManyToManyField(Group, verbose_name=_('groups'), |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def subclass_exception(name, bases, module, attached_to): | |
""" | |
Create exception subclass. Used by ModelBase below. | |
The exception is created in a way that allows it to be pickled, assuming | |
that the returned exception class will be added as an attribute to the | |
'attached_to' class. | |
""" | |
return type(name, bases, { | |
'__module__': module, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if not abstract: | |
new_class.add_to_class( | |
'DoesNotExist', | |
subclass_exception( | |
'DoesNotExist', | |
tuple( | |
x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract | |
) or (ObjectDoesNotExist,), | |
module, | |
attached_to=new_class)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Model(metaclass=ModelBase): | |
def __init__(self): | |
print(f"Inside __init__ of Model with: {self}") | |
super(Model, self).__init__() # object's __init__ | |
class Student(Model): | |
def __init__(self): |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ModelBase(type): | |
a_variable_from_metaclass = 3 | |
_instances = dict() # keep track of the instances created per class | |
@classmethod | |
def __prepare__(metacls, name, bases, **kwargs): # called first | |
print(f"\nInside MetaClass __prepare__, name: {name}, bases: {bases}, metacls: {metacls}, kwargs: {kwargs}") | |
namespace = super().__prepare__(name, bases, **kwargs) | |
print(f"Returned namespace: {namespace}") | |
return namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(f"\nFirst access of grade attribute on student: {student.grade}") | |
student.__setattr__("grade", 12) | |
print(f"\n{student} instance symbol table: {student.__dict__}") | |
print(f"\nSecond access of grade attribute on student: {student.grade}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
student = Student() | |
print(f"\nFirst access of name attribute on student: {student.name}") | |
student.__setattr__("name", "Yu Chen") | |
print(f"\n{student} instance symbol table: {student.__dict__}") | |
print(f"\nSecond access of name attribute on student: {student.name}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Student: | |
def __init__(self): | |
print(f"\n__init__ called on Student.") | |
def __getattribute__(self, key): | |
print(f"\n__getattribute__ invoked on Student with key {key}") | |
v = super(Student, self).__getattribute__(key) | |
if hasattr(v, '__get__'): |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NameDescriptor: | |
""" | |
NameDescriptor is a data descriptor because it implements __get__ and one of either __set__ or __del__ | |
""" | |
def __init__(self, name='Any Name'): | |
print(f"\n__init__ called on NameDescriptor.") | |
self.name: str = name | |
def __get__(self, instance, klass) -> str: |