Django Polymorphic Associations Tutorial

소개



내 기사 Django가 다른 Polymorphic과 거동이 다른 건 에서 Django의 PolymorphicModel이 소위 폴리모픽 관련과 다른 것을 기사로 했습니다.
이번에는 "그럼 Django에서 폴리모픽 관련을 구현하려면 어떻게 할까"라는 점에 대해 설명합니다.

환경


  • Python 3.7.5
  • 장고 2.2.1
  • SQLite

  • 목표



    RailsGuide의 PolymorphicAssociations 장에서는 다음과 같이 폴리모픽 관련이 구현되어 있습니다.
    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
    

    이것에 다음의 ER과 같은 속성을 갖게 한 Model을 구현하는 것을 목표로 합니다.


    coontent_type는 어떤 테이블과 연관되어 있는지를 나타내고, object_id는 어떤 레코드가 연관되어 있는지를 나타냅니다.

    구현



    모델링


    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()
    

    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()
    

    동작 확인


    # マイグレーション
    $ python manage.py makemigrations polymorphic_associations
    $ python manage.py migrate polymorphic_associations
    $ python manage.py shell
    
    
    # データ作成
    >>> 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)>
    
    
    # データ取得
    >>> 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'
    
    
    # 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
        )'
    

    작성된 데이터는 content_type_id , object_id 에 의해 테이블, 레코드를 식별할 수 있음을 알 수 있습니다.
    이것에 의해 이미지를 가지는 테이블은 모두 Imageable 를 계승하는 것으로 신속하게 구현할 수가 있습니다. 또한 이미지에 대한 처리를 Imageable로 구현함으로써 로직이 각 모델이나 서비스에 분산되는 것을 막을 수 있습니다.
    이 소스 코드는 Git에 올려져 있습니다.

    참고


  • htps : // 굳이 s. 루병라이 LS. rg/아소시 아치온_바시cs. html #poly
  • h tps : // s t c ゔ ぇ rf ぉ w. 코 m / 쿠에 s 치온 s / 51824934 / HO W-TO-MAKE-A-D-chango-mo-l-comen B
  • 좋은 웹페이지 즐겨찾기