Suppose there is a <Person> . It can have only one (one to one) transport. Transport can be <Car> , <Airplane> , <Horse> , that is, these three classes are completely different.

How to implement the model? I look towards ContentTypes. I read the dock, but not everything is clear yet, and therefore I am not quite sure about the choice of direction.

If contenttypes is still the right choice, then can you give an example for a push, based on the task above?

    1 answer 1

    ContentTypes allow you to actually refer to instances of different models. If you want to solve your problem through them, then you must create the fields as described in the documentation :

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

    Well, in the future, you can assign instances of the Human model as transport instances of any models registered in django.

    But I would have done without them. You can create a class of transport, and from it to inherit a car, plane, 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) 

    That is, now we have different attributes in different models. I will not list them all, they are well read in the code. It is only necessary to note that we now have a common Transport model with fields specific to all vehicles and types of transport inherited from it, which define their attributes.

    How to use it? Let's look at everything with 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> 
    • "" " But I would do without them at your place. You can create a class of transport, and from it follow the car, aircraft, horse " "" How does this help to accomplish the specified task? After all, the relationship is still between tables, not between classes. What, then, will return the "transport" field? What models? - Mr Fix
    • @Mr.Fix added examples - FeroxTL