[PYTHON] L'histoire du champ de modèle Django disparaissant de la classe

Aperçu

«J'ai regardé ce que mon collègue avait annoncé, je l'ai recherché moi-même et en ai pris note.

Variable de classe

class Person:
    name = 'takanory'
    
Person.name # => takanory

p1 = Person()
p1.name # => takanory

assert Person.name is p1.name  # same object

Le champ disparaît du modèle Django

class Person(models.Model):
    name = models.CharField(max_length=255, default='takanory')
    age = 37

#Des variables de classe ordinaires existent
Person.age # => 37
    
#La variable de classe "nom" de l'objet champ est manquante
Person.name 
# => AttributeError: type object 'Person' has no attribute 'name'

#En fait, "nom" est "_meta.Existe dans "champs"
Person._meta.fields
# => (<django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: name>)

――Pas étonnant pour ceux qui utilisent habituellement Django

Classes et métaclasses

«Pour répondre à cette question, nous devons parler de métaclasses. -Vous pouvez créer un objet de classe avec ** type **

#Définition de classe ordinaire
class Person:
    name = 'takanory'

#Créez le même objet de classe "Personne" que la définition de classe ci-dessus
Person = type('Person', tuple(), {'name': 'takanory'})

#L'objet de classe est une instance de type
assert isinstance(Person, type)
class Taka22(type):
    """ 
nom est'takanory'Uniquement dans le cas de
    nickname = 'taka22'Meta class pour ajouter une variable de classe appelée
    """
    def __new__(cls, name, bases, attrs):
        if attrs.get('name') == 'takanory':
            attrs['nickname'] = 'taka22'
        return super().__new__(cls, name, bases, attrs)  

class Person(metaclass=Taka22):
    name = 'takanory'
 
Person.nickname # => 'taka22'

Suivez la source de Django

――À ce stade, vous pouvez imaginer que la métaclasse fait le "champ disparaît" de la classe.

Vérifiez la métaclasse de la classe Model

class Model(six.with_metaclass(ModelBase)):
    _deferred = False

    def __init__(self, *args, **kwargs):

# refs https://github.com/django/django/blob/master/django/db/models/base.py#L355
# python3
class Hoge(metaclass=NewMeta):

# python2
class Hoge(object):
    __metaclass__ = NewMeta

# python3 and python2
class Hoge(six.with_metaclass(NewMeta):

Où le champ est effacé

--Dans la métaclasse ** ModelBase , attrs (contenant des variables de classe) n'est pas passé à new (super_new) dans la classe parente ( type **) -Seul ** __module __ ** est passé comme attrs. À ce stade, toutes les variables de classe telles que les objets de champ ont disparu de la définition de classe.

class ModelBase(type):
    """
    Metaclass for all models.
    """
    def __new__(cls, name, bases, attrs):
        #Classe parent(type)de__new__Méthode
        super_new = super(ModelBase, cls).__new__

        # ~réduction~

        # Create the class.
        module = attrs.pop('__module__')
        #passer uniquement le module comme attr et nouveau_Classe de génération
        #À ce stade, les variables de classe ont disparu
        new_class = super_new(cls, name, bases, {'__module__': module})

# refs https://github.com/django/django/blob/master/django/db/models/base.py#L67             

Déplacer les champs vers ** _meta.fields **

def add_to_class(cls, name, value):
    # We should call the contribute_to_class method only if it's bound
    if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'):
        value.contribute_to_class(cls, name) #value est un objet de champ
    else:
        # contribute_to_Je n'ai pas de cours
        #attr est défini comme dans la définition de classe(Être retourné)
        setattr(cls, name, value)

# refs https://github.com/django/django/blob/c339a5a6f72690cd90d5a653dc108fbb60274a20/django/db/models/base.py#L303

-Réglé sur ** Model._meta.fields ** dans ** contrib_to_class ** de ** Field **

def contribute_to_class(self, cls, name, private_only=False, virtual_only=NOT_PROVIDED):
    # ~réduction

    #A propos de cette zone, j'ai reçu des cls(=model)de_Je m’ajoute en tant que champs à la méta.
    self.model = cls
    if private_only:
        cls._meta.add_field(self, private=True)
    else:
        cls._meta.add_field(self)
    if self.choices:
        setattr(cls, 'get_%s_display' % self.name,
                    curry(cls._get_FIELD_display, field=self))

# refs https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L678

Résumé

class Person(models.Model):
    name = models.CharField(max_length=255, default='takanory')
    
p1 = Person()
p1.name # => 'takanory'

#L'instance peut faire directement référence à la chaîne de valeur "takanory"
#Lorsque le modèle Person s'instancie, self.La "valeur" du champ est affectée au nom
#Dans le même temps, la variable de classe "Personne."nom" est "soi".Ne peut pas être référencé par "nom"
#Par conséquent, "Personne._meta.N'est-il pas évacué vers des "champs"??

référence

Recommended Posts

L'histoire du champ de modèle Django disparaissant de la classe
L'histoire du lancement d'un serveur Minecraft depuis Discord
L'histoire de l'exportation d'un programme
DJango Memo: depuis le début (réglage du modèle)
L'histoire du traitement A du blackjack (python)
DJango Memo: depuis le début (création d'une vue)
L'histoire de l'affichage des fichiers multimédias dans Django
L'histoire de la création d'un générateur d'icônes mel
Histoire de passer de Pipenv à la poésie
Python scikit-learn Une collection de conseils de modèles prédictifs souvent utilisés sur le terrain
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
L'histoire de Django créant une bibliothèque qui pourrait être un peu plus utile
Python scikit-learn Une collection de conseils de modèles prédictifs souvent utilisés sur le terrain
L'histoire de sys.path.append ()
Une histoire qui réduit l'effort de fonctionnement / maintenance
Le mur lors du passage du service Django de Python 2.7 à la série Python 3
Calculer le volume à partir de la structure bidimensionnelle d'un composé
Implémentation python de la classe de régression linéaire bayésienne
Points Python du point de vue d'un programmeur en langage C
L'histoire de la création d'un réseau neuronal de génération musicale
Remarque DJango: depuis le début (en utilisant une vue générique)
Remarque DJango: depuis le début (création d'une vue à partir d'un modèle)
Faire du modèle une chaîne sur le modèle HTML Django
Une histoire sur le changement du nom principal de BlueZ
Le problème Zip 4 Gbyte est une histoire du passé
Une histoire qui a analysé la livraison de Nico Nama.
[Django] Donne à Form une valeur initiale dynamique de Model
L'histoire du passage de WoSign à Let's Encrypt pour un certificat SSL gratuit
L'histoire de la création d'un canal VIP dans le chatwork en interne
Remarque DJango: depuis le début (Simplification et fractionnement d'URLConf)
L'histoire de la construction de Zabbix 4.4
Personnalisation du champ de modèle Django Divers
Différent du type d'importation de python. Signification de depuis A import B
J'ai fait une fonction pour vérifier le modèle de DCGAN
Une histoire qui rend le débogage de modèle plus facile à voir dans l'environnement Django + SQLAlchemy
L'histoire de la copie de données de S3 vers TeamDrive de Google
Utiliser le modèle django de l'interpréteur
Créer un diagramme de corrélation à partir de l'historique des conversations de Twitter
Après tout, l'histoire du retour de Linux à Windows
Analysez le modèle thématique pour devenir romancier avec GensimPy3
L'histoire de la création d'une base de données à l'aide de l'API Google Analytics
L'histoire de la création d'un bot de boîte à questions avec discord.py
Une histoire sur la prédiction des préfectures à partir des noms de villes avec Jubatus
[Django] Que faire quand il y a de nombreux champs dans le modèle que vous souhaitez créer
Créer une instance d'une classe prédéfinie à partir d'une chaîne en Python
Une histoire coincée avec l'installation de la bibliothèque de machine learning JAX
Une formule qui calcule simplement l'âge à partir de la date de naissance
L'histoire de la création d'un pilote standard pour db avec python.
[Python] Obtenir la date de mise à jour d'un article d'actualité à partir de HTML
[Django] Corrige le pluriel du nom du modèle sur l'écran de gestion
L'histoire de la création d'un site qui répertorie les dates de sortie des livres
Évaluer les performances d'un modèle de régression simple à l'aide de la validation d'intersection LeaveOneOut
Évaluer la précision du modèle d'apprentissage par test croisé de scikit learn
L'histoire de la création d'un module qui ignore le courrier avec python
Meilleur 3 des impressions de la lecture du nouveau manuel de programmation shell
L'histoire de l'échec de la mise à jour de "calendar.day_abbr" sur l'écran d'administration de django
L'histoire de Python et l'histoire de NaN