Django Rest Framework ссылается на базу данных по умолчанию для проверки ограничений отношений (например, для внешнего ключа). - PullRequest
1 голос
/ 02 апреля 2020

Я использую DRF для создания API-интерфейсов CRUD, и мне приходится иметь дело с несколькими базами данных (имеющими одну и ту же схему) в зависимости от запроса.

models.py

class CustomerMaster(models.Model):
    customer_key = models.IntegerField(db_column='CUSTOMER_KEY', primary_key=True)  # Field name made lowercase.
    first_name = models.TextField(db_column='FIRST_NAME', blank=True, null=True)  # Field name made lowercase.
    last_name = models.TextField(db_column='LAST_NAME', blank=True, null=True)  # Field name made lowercase.
    email = models.CharField(db_column='EMAIL', max_length=255, blank=True, null=True)  # Field name made lowercase.
    gender = models.TextField(db_column='GENDER', blank=True, null=True)  # Field name made lowercase.
    dob = models.DateField(db_column='DOB', blank=True, null=True)  # Field name made lowercase.
    phone = models.CharField(db_column='PHONE', max_length=255, blank=True, null=True)  # Field name made lowercase.
    address = models.TextField(db_column='ADDRESS', blank=True, null=True)  # Field name made lowercase.
  ...

    class Meta:
        db_table = 'customer_master'

    def __str__(self):
        return self.first_name + self.last_name

class Folder(models.Model):
    name = models.CharField(max_length=100)
    sib_id = models.IntegerField(unique=True, null=True)

    def __str__(self):
        return self.name

class Segment(models.Model):
    name = models.CharField(max_length=100)
    folder = models.ForeignKey(Folder, on_delete=models.CASCADE, null=True)
    selection = JSONField()
    createdAt = models.DateTimeField(auto_now_add=True)
    updatedAt = models.DateTimeField(auto_now=True)
    createdBy = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    contact = models.ManyToManyField(CustomerMaster)
    sib_id = models.IntegerField(unique=True, null=True)

    def __str__(self):
        return self.name

serializers.py


class SegmentSerializer(serializers.ModelSerializer):
    contact = serializers.SlugRelatedField(many=True, queryset=CustomerMaster.objects.all(), slug_field='email')
    createdBy = UserSerializer(required=False)

    class Meta:
        model = Segment
        fields = ('id', 'name', 'folder', 'selection', 'createdAt', 'updatedAt', 'createdBy', 'contact', 'sib_id')

    def create(self, validated_data):
        club = self.context['club']
        contact_data = validated_data.pop('contact')
        segment = Segment.objects.using(club).create(**validated_data)
        segment.contact.add(*contact_data)
        return segment

    def update(self, instance, validated_data):
        club = self.context['club']
        instance.contact.clear()
        contact_data = validated_data.pop('contact')
        instance.name = validated_data.get('name', instance.name)
        instance.folder = validated_data.get('folder', instance.folder)
        instance.selection = validated_data.get('selection', instance.selection)
        instance.save(using=club)
        instance.contact.add(*contact_data)
        return instance

views.py

class SegmentList(generics.ListCreateAPIView):
    serializer_class = SegmentSerializer

    def get_queryset(self):
        club = self.kwargs['club']
        return Segment.objects.using(club).all()

    def post(self, request, club, format=None):
        serializer = SegmentSerializer(data=request.data, context={'club': club})
        if serializer.is_valid():
            folder = get_object_or_404(Folder.objects.using(club).all(), pk=int(request.data["folder"]))
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Здесь, в моей модели сегмента, папка является внешним ключом, относящимся к модели папки. Мне нужно использовать базу данных на основе URL-адреса запроса, и все базы данных имеют одинаковые схемы. Запрос GET работает нормально. Однако для запросов POST и PUT DRF проверяет ограничение внешнего ключа папки в базе данных по умолчанию. Например, запрос POST:

{
        "name": "Testing",
        "folder": 8,
        "selection": "{'testing': 20}",
        "contact": []
}

Он дает мне следующий ответ:

{
    "folder": [
        "Invalid pk \"8\" - object does not exist."
    ]
}

Но папка с pk "8" существует в предполагаемой базе данных.

Я использую python 3.7, django 2.2.11, django rest framework 3.11.0

Буду признателен за любую помощь. Заранее спасибо!

...