создание объекта на основе некоторых условий в django - PullRequest
0 голосов
/ 11 февраля 2020

У меня есть модель под названием Showcase, которую пользователи используют для демонстрации проектов. Я пытаюсь реализовать случай, когда любой администратор в поле Administrators в витрине может добавить соавторов через модель Collaborator. Когда я запускаю свой код ниже, я получаю

IntegrityError at /api/showcase/the-gods-must-be-crazy-zz2fox/collaborator/create/ NOT NULL constraint failed: showcase_collaborator.user_id.

models.py

class Showcase(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField(null=True)
    skill_type = models.ForeignKey(Skill, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="Showcases")
    content = models.TextField(null=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    voters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="upvotes")
    slug = models.SlugField(max_length=255, unique=True)
    administrator = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="administrators", blank=True)


class Collaborator(models.Model):
    post = models.ForeignKey(Showcase, on_delete=models.CASCADE, related_name="collaborated_showcases")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, 
                            on_delete=models.CASCADE, related_name="collaborators")
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE, null=True, related_name="creative_type")
    role = models.TextField(null=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)

сериализатор

class CollaboratorSerializer(serializers.ModelSerializer):
    post = serializers.SlugRelatedField(read_only=True, slug_field='slug')

    class Meta:
        model = Collaborator
        exclude = ['created_on', 'updated_on']

class ShowcaseAdminSerializer(serializers.ModelSerializer):
    administrator = serializers.SlugRelatedField(slug_field='slug', many=True, queryset=User.objects.all())

    class Meta:
        model = Showcase
        fields = ['administrator',]

    def update(self, instance, validated_data):
        users = validated_data.get('administrator')
        for user in users:
            instance.administrator.add(user)
        return instance

views.py

class collaboratorCreateView(APIView):
    '''
    add collaborator to a showcase
    '''
    serializer_class = CollaboratorSerializer
    permission_classes = [IsAdmin]

    def post(self, request, slug):
        showcase = get_object_or_404(Showcase, slug=slug)

        try:
            self.check_object_permissions(request, showcase)
            collaborator = Collaborator.objects.create(
                post = showcase
            )
            serializer = self.serializer_class(collaborator, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except APIException:
            return Response(status=status.HTTP_403_FORBIDDEN)

URL-адреса

path("<slug:slug>/collaborator/create/", qv.collaboratorCreateView.as_view(), name="add-collaborator-to-showcase"),

Кроме того, мне было интересно, как предотвратить создание дублирующего пользователя в качестве соавтора, если это возможно. Я предполагаю, что оператор if МОЖЕТ решить проблему, но я заблудился об этом, потому что я не знаю, как получить пользовательский ввод для проверки в представлении.

1 Ответ

1 голос
/ 12 февраля 2020

Как говорится в сообщении об ошибке, вам необходимо указать значение атрибута user в модели. Таким образом, вы можете сделать это следующим образом.

Сначала обновите сериализатор:

class CollaboratorSerializer(serializers.ModelSerializer):
    post = serializers.SlugRelatedField(read_only=True, slug_field='slug')

    class Meta:
        model = Collaborator
        exclude = ['created_on', 'updated_on', 'user']

    def validate_user(self, value):
        showcase = self.context.get('post')
        if showcase.collaborated_showcases.filter(user=value).exists():
            raise serializers.ValidationError("Can't add an existing collaborator to a showcase")
        return value

   def create(self, validated_data):
       validated_data['post'] = self.context['post']
       return super(CollaboratorSerializer, self).create(validated_data)

Затем обновите представление:

class collaboratorCreateView(APIView):
    '''
    add collaborator to a showcase
    '''
    serializer_class = CollaboratorSerializer
    permission_classes = [IsAdmin]

    def post(self, request, slug):
        showcase = get_object_or_404(Showcase, slug=slug)

        try:
            self.check_object_permissions(request, showcase)
            serializer = self.serializer_class(data=request.data, context={'post':showcase})
            if serializer.is_valid():
                serializer.save()

Здесь я передаю showcase объект для Сотрудника через context.

...