[PYTHON] Didacticiel sur les associations polymorphes Django

introduction

Mon article Django se comporte différemment des autres polymorphes J'ai écrit sur le fait que le modèle polymorphe de Django est différent du soi-disant polymorphe lié. Cette fois, j'expliquerai le point "Comment implémenter ** lié polymorphe ** dans Django".

environnement

objectif

Dans le chapitre Polymorphic Associations du guide Rails, la relation polymorphique est implémentée comme suit.

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end
 
class Employee < ApplicationRecord
  has_many :pictures, as: :imageable
end
 
class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

L'objectif est d'implémenter un modèle qui possède les attributs de type ER suivants.

imageable.png

coontent_type indique quelle table est associée et ʻobject_id` indique quel enregistrement est associé.

la mise en oeuvre

La modélisation

from django.db import models
from django.contrib.contenttypes.models import ContentType


class Picture(models.Model):
    object_id = models.IntegerField(db_index=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    file_name = models.CharField()


class Employee(models.Model):
    name = models.CharField()
    email = models.EmailField()


class Product(models.Model):
    name = models.CharField()
    price = models.IntegerField()

Implémentation de la classe imageable

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType


class Picture(models.Model):
    object_id = models.IntegerField(db_index=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    file_name = models.CharField(max_length=256)
    content_object = GenericForeignKey('content_type', 'object_id')


class Imageable(models.Model):
    class Meta:
        abstract = True

    pictures = GenericRelation(Picture)


class Employee(Imageable):
    name = models.CharField(max_length=256)
    email = models.EmailField()


class Product(Imageable):
    name = models.CharField(max_length=256)
    price = models.IntegerField()

Contrôle de fonctionnement

#migration
$ python manage.py makemigrations polymorphic_associations
$ python manage.py migrate polymorphic_associations
$ python manage.py shell


#Création de données
>>> from polymorphic_associations.models import Employee, Product
>>>
>>> employee = Employee(name='John', email='[email protected]')
>>> employee.save()
>>> employee.pictures.create(file_name='employee.jpg')
<Picture: Picture object (1)>
>>>
>>> product = Product(name='Desk', price=1000)
>>> product.save()
>>> product.pictures.create(file_name='product.jpg')
<Picture: Picture object (2)>


#L'acquisition des données
>>> employee.pictures.all()
<QuerySet [<Picture: Picture object (1)>]>
>>> employee.pictures.first().file_name
'employee.jpg'
>>>
>>> product.pictures.all()
<QuerySet [<Picture: Picture object (2)>]>
>>> product.pictures.first().file_name
'product.jpg'


#Confirmation SQL
>>> str(employee.pictures.all().query)
'SELECT
    "polymorphic_associations_picture"."id",
    "polymorphic_associations_picture"."object_id",
    "polymorphic_associations_picture"."content_type_id",
    "polymorphic_associations_picture"."file_name"
FROM
    "polymorphic_associations_picture"
WHERE
    (
        "polymorphic_associations_picture"."content_type_id" = 2
    AND "polymorphic_associations_picture"."object_id" = 1
    )'
>>>
>>> str(product.pictures.all().query)
'SELECT
    "polymorphic_associations_picture"."id",
    "polymorphic_associations_picture"."object_id",
    "polymorphic_associations_picture"."content_type_id",
    "polymorphic_associations_picture"."file_name"
FROM
    "polymorphic_associations_picture"
WHERE
    (
        "polymorphic_associations_picture"."content_type_id" = 3
    AND "polymorphic_associations_picture"."object_id" = 1
    )'

Vous pouvez voir que les données créées peuvent identifier la table et l'enregistrement par content_type_id et ʻobject_id. Cela permet à toutes les tables avec des images d'être implémentées rapidement en héritant de ʻImageable. De plus, en implémentant le traitement d'image dans Imageable, il est possible d'empêcher la logique d'être distribuée à chaque modèle et service. Ce code source peut être trouvé dans Git.

référence

Recommended Posts

Didacticiel sur les associations polymorphes Django
Tutoriel Python Django (5)
Tutoriel Python Django (2)
mémo du didacticiel django
Tutoriel Python Django (8)
Tutoriel Python Django (6)
Démarrer le didacticiel Django 1
Tutoriel Python Django (7)
Tutoriel Python Django (1)
Tutoriel du didacticiel Python Django
Tutoriel Python Django (3)
Tutoriel Python Django (4)
Résumé du didacticiel Python Django
tutoriel simple django oscar
Note du didacticiel Django Girls
Lancez-vous avec Django! ~ Tutoriel ⑤ ~
Lancez-vous avec Django! ~ Tutoriel ④ ~
Lancez-vous avec Django! ~ Tutoriel ⑥ ~
Fiche technique du didacticiel Python Django
Django
Résumé du didacticiel Django Girls Première moitié
Trébucher lors du didacticiel django 1.7
Déployer le didacticiel Django sur IIS ①
Tutoriel Django Crispy (Construction d'environnement sur Mac)
Résumé du tutoriel Django pour les débutants par les débutants ③ (Afficher)
Tutoriel Django (Créer une application de blog) ⑤ --Fonction de création d'article
Tutoriel de clé externe de Django en 10 minutes
Tutoriel Django (Créer une application de blog) ④ --Test d'unité
Résumé du tutoriel Django pour les débutants par les débutants ⑤ (test)