【问题标题】:Validate POST request (Vue + DRF)验证 POST 请求(Vue + DRF)
【发布时间】:2019-12-17 09:24:59
【问题描述】:

所以这是请求的预期流程:

  1. 用户通过 html 表单创建一个新的Language。 [√]
  2. Vue 通过 axios 将向 drf 发出 POST 请求。 [√]
  3. Drf 将验证来自 POST 请求的数据(查看语言名称/id/等是否已经存在)[x]
  4. 如果通过验证,则创建新语言。 [x]

我目前卡在#3。

我试着把它放在我的LanguageViewSet:

def post(self, request):
    language = request.data.get('language')
    serializer = LanguageSerializer(data=language)
    if serializer.is_valid(raise_exception=True):
        language_saved = serializer.save()
    return Response({"success": "Language '{}' created successfully!".format(language_saved.name)})

但是,这在某种程度上不起作用并被完全忽略,因为:

  1. 我尝试评论发布功能,但如果我通过 LanguageViewSet 上的 axios 调用 POST 请求,它仍然会发布。可能是内置的 POST 功能?
  2. 如果有这个功能,注意我用language = request.data.get('language'),意思是在我的axios上,我要发送的数据的名字应该是language吧?否则它将忽略 POST 请求。我在 axios 中使用了created_lang,触发了 POST 请求,但它仍然没有任何错误地发布,就好像它完全忽略了我的 post 函数一样。
  3. 如果我尝试发布其名称已在数据库中注册的新语言,它仍会创建重复记录。

原谅我的幼稚,我对 drf 和 django 完全陌生:

这是我的代码:

Language模特:

class Language(models.Model):
    name = models.CharField(max_length=100, default='New Language')
    def __str__(self):
        return self.name

它的serializer:

class LanguageSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Language
        fields = ['id', 'name']

view:

class LanguageViewSet(viewsets.ModelViewSet):
    queryset = Language.objects.all().order_by('name')
    serializer_class = LanguageSerializer

    def get_queryset(self):
        queryset = Language.objects.all().order_by('name')
        lang = self.request.query_params.get('lang','')
        if lang:
            return Language.objects.filter(pk=lang)
        else:
            return queryset    

和url:

router = routers.DefaultRouter()
router.register(r'languages', views.LanguageViewSet)

在我的前端,这是我的表单:

<form @submit.prevent="PostLanguage" class="mt-3" action='' method="POST">
    <input type="text" v-model="created_lang.name" name="name" id="name" placeholder="Language Name" autocomplete="off" required>
    <input type="submit" value="Post">
</form>

并将通过这个简单的 Vue 脚本发布:

PostLanguage(){
    let params = Object.assign({}, this.created_lang)
    axios.post(
        'http://127.0.0.1:8000/api/languages/', params
    )
    .then(response=>{
        console.log(response)
        this.GetLanguages()
        this.created_lang.name = ''
    })
    .catch(error => {
        console.log(error)
    })
}

更新

我试过了:

class LanguageSerializer(serializers.ModelSerializer):
class Meta:
    model = Language
    fields = ['id', 'name']

def validate_name(self, value):
    existed_language = Language.objects.filter(name=value).get()
    if existed_language.name == value:
        return Response(status=400)
    else:
        return value

如果来自 POST 的 name 数据是新的(它没有在数据库中使用),那么它将返回它的 value,从而创建一种新语言。但是,如果它已经存在,我尝试返回一个响应,但它会创建一个名称 = &lt;Response status_code=400, "text/html; charset=utf-8"&gt; 的语言。我知道这有点好笑,但我认为这是朝着正确方向迈出的一步。

【问题讨论】:

  • 语言是独一无二的吗?
  • @a_k_v 是的,应该是。

标签: python django vue.js django-rest-framework


【解决方案1】:

如果语言在您的模型中是唯一的,则在您的模型定义中添加唯一的 true。

class Language(models.Model):
    name = models.CharField(max_length=100, default='New Language', unique=True)
    def __str__(self):
        return self.name

这将导致 serializer.validate 失败并且不会创建重复的语言。

更新

序列化程序中的 validate_name 在执行验证逻辑后返回字段的值。因此,您可以使用 raise serializers.ValidationError("Language already exist") 而不是 Response (400) 语句对其进行更新。

【讨论】:

  • 非常感谢!!在结束之前,我还有几个问题。 1.哪个更好?设置模型的unique=True 或在其序列化程序中编写自己的验证器? 2.在返回的响应中,即error.response.request,有一个字段:response: "{"name":["Language already exist"]}"我怎样才能得到这个返回的文本?再次非常感谢! :)
  • 对于您的第一个查询,最好在模型级别设置 unique true。因为每次您可能不会使用序列化程序将数据插入模型。在这种情况下,您的序列化程序中的验证无用。
  • 以及关于 django 中错误消息的一般格式的错误消息。
猜你喜欢
  • 1970-01-01
  • 2018-03-23
  • 2020-06-16
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多