【问题标题】:django rest api - adding users to keyword modeldjango rest api - 将用户添加到关键字模型
【发布时间】:2018-12-05 17:46:04
【问题描述】:

我想在我的 rest api 中实现一个功能,用户可以为新闻提要添加特定的关键字。

因此,如果用户使用关键字进行发布请求,则用户对象将添加到预定义的关键字(在数据库中预定义)。

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

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

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

使用此标头制作:

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

Body:
{
"name": "keyword1"
}

授权有效,因此用户添加到空关键字

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

这些是实现的 sn-ps:

models.py

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

    def __str__(self):
        return self.name

序列化器.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,
        })

【问题讨论】:

  • 您能否澄清一下“将添加关键字但不添加提供的 json 数据”的意思?它只是添加一个关键字,其中name 是一个空字符串吗?另外,尝试在 post 方法中打印 request.data 以查看原始数据中的名称。
  • @slider 如果我在 post 请求中使用 json 数据 {„name“:“keyword1”} 将用户添加到特定关键字,那么 django 只保存一个空字符串作为关键字

标签: django django-models django-rest-framework django-serializer


【解决方案1】:

你做错的事情很少

第一 您的模型名称是 Keywords 它不应该是复数使用 Keyworduser 字段是 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)

【讨论】:

  • 您好,我尝试了您的解决方案,但出现不允许使用 POST 方法的错误。我尝试添加 def post(self, request, format=None): return Response("ok"),但他没有创建任何关键字
【解决方案2】:

试试这个 sn-p:

class KeywordSerializer(serializers.ModelSerializer): user = serializers.HiddenField(default=serializers.CurrentUserDefault()) class Meta: model = Keywords fields = '__all__' def create(self, validated_data): user = validated_data.pop('user') kw = Keywords.objects.create(**validated_data) kw.user.add(user) kw.save() return kw

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 类,因为它对于CURD 应用程序非常方便,而HiddenField 类似于write_only=True 字段参数。

参考资料:

  1. DRF - Modelviewset
  2. HiddenField
  3. CurrentUserDefault

【讨论】:

  • 好吧,那是我的错,您的解决方案是正确的,非常感谢!我现在学到了很多
  • @marc_s 我不明白你为什么要编辑我的答案,我认为这无关紧要
  • 我修正了一个明显的错字 - 我在几乎所有你的回复中都发现了一个 - 它是 references - 只有一个 f(不是两个,当您继续使用时)。我也删除了所有那些不必要的<br> 标签——只是想让事情变得更好、更流畅、更少错别字等。
  • 我理解我的错别字。感谢那。但是我对你的代码 sn-p 编辑感觉不太好。我想强调一些线条,所以我将这些线条设为粗体。在您的代码清理之后,一些标签仍然存在......这不好。
  • @marc_s 总之,请还原那些 code sn-p 格式,因为我真的认为code lines with **bold** format 是必要的
【解决方案3】:

对于那些可能有同样问题的人,这里是完整的解决方案: 感谢 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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-23
    • 2016-04-17
    • 2010-09-23
    • 2018-07-28
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多