django rest api - 将用户添加到关键字模型

django rest api - adding users to keyword model

我想在休息时实现一项功能 api,用户可以为新闻提要添加特定关键字。

因此,如果用户使用关键字发出 post 请求,用户 object 将被添加到预定义关键字(在数据库中预定义)。

我已经用这段代码试过了,但是如果我尝试用 postman 模拟 post 请求,我总是遇到这个问题:

将添加关键字,但不会添加提供的 json 数据,它只是一个空字符串,post 请求 returns 也是一个空关键字...

我希望你能帮助我,也许你能给我一个建议如何只允许已经定义的静态关键字并允许用户只有一个关键字一次(没有相同值的双关键字)

用这个 headers:

[{"key":"Content-Type","value":"application/json","description":""}]
[{"key":"Authorization","value":"Token xxxxxxx","description":""}]

Body:
{
"name": "keyword1"
}

授权有效,所以用户添加了空关键字

我是 django 的新手,我正在做这个项目来提高我的技能,所以请对我宽容 :) 所以它可能是完全错误的,请给我一些建议来解决我的问题

这些是实施的片段:

models.py

class Keywords(models.Model):
    name = models.CharField(max_length=200)
    user = models.ManyToManyField(User)

    def __str__(self):
        return self.name

serializers.py

class KeywordSerializer(serializers.Serializer):
    class Meta:
        model = Keywords
        fields = ('id', 'name', 'user')

    def create(self, validated_data):
            keyword = Keywords(**validated_data)
            keyword.save()
            keyword.user.add(self.context['request'].user)
            return keyword

views.py

class KeywordAPI(generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = KeywordSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        keyword = serializer.save()
        return Response({
            "name": KeywordSerializer(keyword, context=self.get_serializer_context()).data,
        })

你做错的地方很少

第一个 你的模型的名字是 Keywords 它不应该是复数使用 Keyword 并且 user 字段是 ManyToMany 所以你应该复数它

class Keyword(models.Model):
    name = models.CharField(max_length=200)
    users = models.ManyToManyField(User)

    def __str__(self):
        return self.name

第二个 您正在使用 Serializer 而不是 ModelSerializer

class KeywordSerializer(serializers.ModelSerializer):
    class Meta:
        model = Keywords
        fields = ('id', 'name', 'users')
        read_only_fields = ('users',)

    def create(self, validated_data):
        keyword = super().create(validated_data)
        keyword.users.add(self.context['request'].user)
        return keyword

第三 您不必使用现有的 mixins

自己编写创建逻辑
from rest_framework import mixins


class KeywordAPI(mixins.CreateModelMixin, generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = KeywordSerializer

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

试试这个片段:


class KeywordSerializer(serializers.<b>ModelSerializer</b>):
    <b>user = serializers.HiddenField(default=serializers.CurrentUserDefault())</b>

    class Meta:
        model = Keywords
        <b>fields = '__all__'</b>

    <b>def create(self, validated_data):
        user = validated_data.pop('user')
        kw = Keywords.objects.create(**validated_data)
        kw.user.add(user)
        kw.save()
        return kw</b>

views:

from rest_framework import viewsets, permissions

class KeywordAPI(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = KeywordSerializer
    queryset = Keywords.objects.all()

输入负载为

{
"name":"kw1"
}

注意
这里我使用了 ModelSerializer class,因为它对 CURD 应用程序非常方便,而 HiddenField 类似于字段的 write_only=True 参数。

参考文献:

  1. DRF - Modelviewset
  2. HiddenField
  3. CurrentUserDefault

对于那些可能有同样问题的人,这里是完整的解决方案: 感谢 Sardorbek Imomaliev 和 Jerin Peter George 对我的帮助

序列化器:

class KeywordSerializer(serializers.ModelSerializer):
users = serializers.HiddenField(default=serializers.CurrentUserDefault())

class Meta:
    model = Keyword
    fields = '__all__'

def create(self, validated_data):
    users = validated_data.pop('users')
    if Keyword.objects.filter(**validated_data).exists():
        kw = Keyword.objects.filter(**validated_data).get()
        kw.users.add(self.context['request'].user)
        return kw
    else:
        raise serializers.ValidationError("This Keyword has not been set yet.")

型号:

class Keyword(models.Model):
name = models.CharField(max_length=200)
users = models.ManyToManyField(User)

def __str__(self):
    return self.name

查看:

class KeywordAPI(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, ]
serializer_class = KeywordSerializer
queryset = Keyword.objects.all()