Je voulais juste ajouter quelque chose que je n'ai pas vu dans les autres réponses.
Contrairement aux classes python, le masquage du nom du champ n'est pas autorisé avec l'héritage des modèles.
Par exemple, j'ai expérimenté des problèmes avec un cas d'utilisation comme le suivant :
J'avais un modèle héritant de l'auth de Django. PermissionMixin :
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'),
blank=True, help_text=_('The groups this user belongs to. A user will '
'get all permissions granted to each of '
'his/her group.'))
user_permissions = models.ManyToManyField(Permission,
verbose_name=_('user permissions'), blank=True,
help_text='Specific permissions for this user.')
class Meta:
abstract = True
# ...
Ensuite, j'avais mon mixin qui, entre autres choses, devait remplacer la fonction related_name
de la groups
champ. C'était donc plus ou moins comme ça :
class WithManagedGroupMixin(object):
groups = models.ManyToManyField(Group, verbose_name=_('groups'),
related_name="%(app_label)s_%(class)s",
blank=True, help_text=_('The groups this user belongs to. A user will '
'get all permissions granted to each of '
'his/her group.'))
J'utilisais ces 2 mixins comme suit :
class Member(PermissionMixin, WithManagedGroupMixin):
pass
Alors oui, je m'attendais à ce que ça marche mais ça n'a pas marché. Mais le problème était plus grave car l'erreur que je recevais ne pointait pas du tout vers les modèles, je n'avais aucune idée de ce qui n'allait pas.
En essayant de résoudre ce problème, j'ai décidé par hasard de modifier mon mixin et de le convertir en un mixin de modèle abstrait. L'erreur s'est transformée en ceci :
django.core.exceptions.FieldError: Local field 'groups' in class 'Member' clashes with field of similar name from base class 'PermissionMixin'
Comme vous pouvez le constater, cette erreur explique ce qui se passe.
C'était une énorme différence, à mon avis :)