Mein Artikel Django verhält sich anders als andere polymorphe Ich schrieb über die Tatsache, dass sich das polymorphe Modell von Django von dem sogenannten polymorphen Modell unterscheidet. Dieses Mal werde ich den Punkt "Wie man ** polymorphe verwandte ** in Django implementiert" erklären.
Im Kapitel [Polymorphe Assoziationen] des Rails-Handbuchs (https://guides.rubyonrails.org/association_basics.html#polymorphic-associations) wird die polymorphe Beziehung wie folgt implementiert.
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
Ziel ist es, ein Modell mit den folgenden ER-ähnlichen Attributen zu implementieren.
coontent_type
gibt an, welche Tabelle zugeordnet ist, und object_id
gibt an, welcher Datensatz zugeordnet ist.
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()
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()
#Migration
$ python manage.py makemigrations polymorphic_associations
$ python manage.py migrate polymorphic_associations
$ python manage.py shell
#Datenerstellung
>>> 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)>
#Datenerfassung
>>> 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-Bestätigung
>>> 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
)'
Sie können sehen, dass die erstellten Daten die Tabelle und den Datensatz anhand von "content_type_id" und "object_id" identifizieren können. Dadurch können alle Tabellen mit Bildern schnell implementiert werden, indem "Imageable" geerbt wird. Sie können auch verhindern, dass die Logik auf Modelle und Dienste verteilt wird, indem Sie die bildbezogene Verarbeitung in Imageable implementieren. Dieser Quellcode befindet sich in Git.
Recommended Posts