ContentTypes. Message? Modelling



  • Let's say it. PERCELLOK♪ He can only have one transport. Transport may be PERAvomometerPERFORMONTHPERLOCATIONI mean, these three classes are completely different.

    How do we make models? Looking towards ContentTypes. I'm reading the doc, but it's not clear yet, and that's why I'm not quite sure about the direction.

    If the content of thetypes is still the right choice, can an example be used, based on the task above?



  • ContentTypes indeed make it possible to refer to copies of different models. If you want to accomplish your task through them, you need to create fields like https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations :

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

    class Car(models.Model):
    pass

    class Plane(models.Model):
    pass

    class Horse(models.Model):
    pass

    class Human(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    transport = GenericForeignKey('content_type', 'object_id')

    In the future, copies of the human model may be assigned as transport copies of any models registered in django.

    But if I were you, I wouldn't do it. You can create a transport class, and you can trace the car, the plane, the horse:

    from django.db import models

    class Transport(models.Model):
    pass

    class Car(Transport):
    pass

    class Plane(Transport):
    pass

    class Horse(Transport):
    pass

    class Human(models.Model):
    transport = models.ForeignKey(Transport)

    UPD:

    For example, we will refine our models as follows:

    class Transport(models.Model):
    max_speed = models.IntegerField('Максимальная скорость')
    capacity = models.IntegerField('Вместимость')

    class Car(Transport):
    doors = models.IntegerField('Количество дверей')

    class Plane(Transport):
    wing_size = models.IntegerField('Размах крыла')

    class Horse(Transport):
    date_birth = models.DateTimeField('Дата рождения')

    class Human(models.Model):
    transport = models.OneToOneField(Transport)

    So now we have different attributes in different models. I won't list them, they're good in the code. All we have to say is we have a common model now. Transport with vehicle-specific floors and modes of transport which are derived from all vehicles and which determine their attributes.

    How do you use it? Let us look at the examples.

    >>> # Создадим по одному экземпляру каждой модели - авто, самолёта и лошади
    >>> Car.objects.create(doors=5, max_speed=130, capacity=5)
    <Car: Car object>
    >>> Plane.objects.create(wing_size=30, max_speed=1100, capacity=80)
    <Plane: Plane object>
    >>> import datetime
    >>> Horse.objects.create(date_birth=datetime.datetime.now() - datetime.timedelta(days=365), max_speed=10, capacity=1)
    <Horse: Horse object>
    >>> # теперь создадим 3 челокека, к которым сразу же привяжем транспорт
    >>> Human.objects.create(transport=Car.objects.first())
    <Human: Human object>
    >>> Human.objects.create(transport=Plane.objects.first())
    <Human: Human object>
    >>> Human.objects.create(transport=Horse.objects.first())
    <Human: Human object>
    >>> # Выбрать все объекты транспорта можно через класс Transport
    >>> Transport.objects.all().values()
    [{'max_speed': 130, 'capacity': 5, u'id': 1}, {'max_speed': 1100, 'capacity': 80, u'id': 2}, {'max_speed': 10, 'capacity': 1, u'id': 3}]
    >>> # теперь рассмотрим как нам в модели человека получить его транспорт
    >>> human = Human.objects.first()
    >>> human.transport
    <Transport: Transport object>
    >>> # через Transport можно также получить и модели, которые наследуются от данного транспорта т.е. лошадь, самолёт или авто. Делается это через доступ к одноимённым атрибутам в экземпляре модели. Проверить какого типа данный транспорт можно воспользовавшись проверкой на hasattr по каждому наследуемому классу
    >>> hasattr(human.transport, 'car')
    True
    >>> hasattr(human.transport, 'car'), hasattr(human.transport, 'horse'), hasattr(human.transport, 'plane')
    (True, False, False)
    >>> # получить объект Car
    >>> human.transport.car
    <Car: Car object>
    >>> # выбрать всех владельцев авто
    >>> Human.objects.filter(transport__car__isnull=False)
    [<Human: Human object>]
    >>> # получить владельца авто
    >>> car = Car.objects.first()
    >>> car.human
    <Human: Human object>




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2