首页 > 解决方案 > 在 django 中根据某些条件创建对象

问题描述

我有一个模型Showcase,用户可以用来展示项目。我正在尝试实现一个案例,Administrators展示中的任何管理员都可以通过Collaborator模型添加协作者。当我在下面运行我的代码时,我得到

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

模型.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

视图.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)

网址

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

另外,作为额外的,我想知道如果可能的话,如何防止创建重复用户作为协作者。我猜测 if 语句可能会解决问题,但我对此感到迷茫,因为我不知道如何获取用户输入以检查视图。

标签: djangodjango-rest-framework

解决方案


正如错误所说,您需要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通过 . 将对象传递给 Collaborator context


推荐阅读