django models-design: "поле ptr обязательно" - PullRequest
0 голосов
/ 30 августа 2018

Я использую Python 3.6 + PostgreSQL 10 + последние Django и DjangoRestFRamework. У меня есть следующие модели, в которых несколько моделей наследуются от класса, который является ForeignKey (One-to-Many) другого класса.

class Voteable(models.Model):
      Voteable_id = models.BigAutoField(primary_key=True);

class base(Voteable):
    class Meta:
        abstract = False

class traslated_info(models.Model):
    info_about=models.ForeignKey(base)
    info_body=models.TextField()
    info_language=models.CharField(max_length=2)

class A(base):
    A_id=models.BigAutoField(primary_key=True)
    A_field=models.TextField()

class B(base):
    B_id=models.BigAutoField(primary_key=True)
    B_field=models.TextField()
    B_belongs_to=models.ForeignKey(A)

class C(base):
    C_id=models.BigAutoField(primary_key=True)
    C_field=models.TextField()
    C_belongs_to=models.ForeignKey(A)
    C_belongs_to=models.ForeignKey(B)

Всякий раз, когда я пытаюсь сохранить объект A (через curl), django говорит, что base_ptr требуется. Я не знаю, как смоделировать эту ситуацию. Не ожидается, что конечный пользователь создаст базу элементов, а затем элемент A, B или C. Я попытался использовать базу классов как абстрактную, но абстрактный класс не может быть ForeignKey. Я хочу автоматически создавать базовый класс всякий раз, когда создается класс A.

Я думаю, что у меня есть два варианта: A) Удалите ForeignKey и сохраните информационные поля для языка как HStoreField. Это делает код зависимым от Postgree. Б) Создайте какую-то подпрограмму, которая автоматически создает родительский базовый элемент всякий раз, когда создается дочерний элемент Элемент (с сохранением отношения один к одному).

Что вы рекомендуете? Есть ли какой-то простой вариант django, который я пропускаю, чтобы сделать вариант B? Я не нашел это. Спасибо.

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Создайте ваш сериализатор, как показано ниже, вам не нужно явно создавать базовые классы, он будет создан автоматически.

class ASerializer(serializers.ModelSerializer):
    class Meta:
        model = A
        read_only_fields = ('base_ptr',)
        fields = '__all__'
0 голосов
/ 31 августа 2018

Наличие автоматического поля в качестве primary_key в моделях A, B или C вызывает эту ошибку, так как создание дочерней модели не приводит к каскадному созданию родителей. Я нашел два обходных пути:

  • Измените параметр автозаполя primary_key на false и добавьте SILENCED_SYSTEM_CHECKS = [ 'fields.E100']
  • Переопределение Viewset создать метод:

@transaction.atomic

def create(self,request,*args,**kwargs):
    request.data['base_ptr'] = base.objects.create(user=request.user,created_date=datetime.utcnow()).pk
    return super(viewsets.ModelViewSet,self).create(request,*args,**kwargs)

Я буду придерживаться второго, я вполне уверен, что больше проблем возникнет.

...