如何在vue模板中显示序列化程序验证错误消息?

时间:2019-08-15 08:33:14

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

在这里,我正在使用vue.js进行客户端渲染,并使用django-REST框架进行服务器端。我正在自定义const arr1 = [ { id: 1, driver: "Mario", carName: "Ferrari 488" }, { id: 2, driver: "Solid Snake", carName: "Prious" }, { id: 3, driver: "Link", carName: "Explorer" }, { id: 4, driver: "Zelda", carName: "Genesis" }, { id: 5, driver: "Ryu", carName: "Range Rover" } ]; const arr2 = [ { id: 6, driver: "Chun-Li", carName: "Lamborghini" }, { id: 7, driver: "Blanca", carName: "Camry" }, { id: 3, driver: "Link", carName: "Explorer" }, { id: 9, driver: "Kurby", carName: "Ferrari 911" }, { id: 1, driver: "Mario", carName: "Ferrari 488" }, ]; const arr1Ids = new Set(arr1.map(({ id }) => id)); arr2.forEach(({ id }) => { if (arr1Ids.has(id)) { console.log('duplicate id:', id); } });类,以检查输入的电子邮件是否已在我们的数据库中注册。如果电子邮件不在我们的数据库中,则它不会发送成功消息,这正是我所期望的。但是未显示验证错误消息。但是,如果没有用户使用该电子邮件地址,我已经在PasswordResetSerializer类中配置了错误消息。

注意:如果电子邮件地址在我们的数据库中,它将显示成功消息PasswordResetSerializer。 验证错误消息也完全显示在我的后端中,但没有显示在vue模板形式中。

当我检查vue模板时,它就给了我

Password reset email has been sent

但是当我通过django-rest后端输入此Bad Request: /api/v1/admin/password/reset/ [15/Aug/2019 17:19:02] "POST /api/v1/admin/password/reset/ HTTP/1.1" 400 69 网址时,它会引发验证错误消息,就像我在代码中配置的一样。但是我也需要在vue模板中显示该消息

如何以忘记密码的形式显示/api/v1/admin/password/reset/消息?

serializers.py

serializers.ValidationError

forgotpassword.vue

from django.contrib.auth.forms import PasswordResetForm
from django.conf import settings


class PasswordResetSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password_reset_form_class = PasswordResetForm

    def validate_email(self, value):
        self.reset_form = self.password_reset_form_class(data=self.initial_data)
        if not self.reset_form.is_valid():
            raise serializers.ValidationError('Error')

        if not User.objects.filter(email=value).exists():
            raise serializers.ValidationError('Sorry.No user found with that email address.')

        return value

    def save(self):
        request = self.context.get('request')
        opts = {

            'from_email': getattr(settings, 'DEFAULT_FROM_EMAIL'),
            'request': request,
        }
        self.reset_form.save(**opts)

views.py

 <template>
    <div class="password-change-card">
      <div class="container">
        <div class="edit-card">
            <img class="edit-icon" src="@/assets/icons/edit.png" alt="">
        </div>
        <form @submit.prevent="sendPasswordResetEmail(email)">
            <div class="input-container">
                <img class="icon-password" src="@/assets/icons/user.png" alt="">
                <input class="username" type="email" v-model="email" placeholder="Email" name="email" required>
            </div>
            <div  class="error-message" v-if="error != null">
                {{ error.non_field_errors[0] }}
            </div>
            <div  class="error-message" v-if="success != null">
                {{ success.detail }}
            </div>
            <button type="submit" class="btn forget-btn">Send Email
                <half-circle-spinner v-if="loading" class="spinner"
                    :animation-duration="1000"
                    :size="30"
                    color="#ffff"
                />
            </button>
        </form>
        <div>
            <router-link to="/login">Login</router-link>
        </div>
      </div>
    </div>
</template>

<script>
import { mapActions, mapState } from 'vuex';
import { HalfCircleSpinner } from 'epic-spinners'
export default {
    components:{
        HalfCircleSpinner,
    },
    data() {
        return { 
            email: '',
            error: null,
            success: null,
            loading:false,
        }
    },
    computed: mapState('password', [
        'emailCompleted',
        'emailError',
        'emailLoading',
    ]),
    beforeRouteLeave(to, from, next) {
        this.clearEmailStatus();
        next();
    },
    methods:{
        sendPasswordResetEmail(email){
            this.loading = true
            this.error = null
            this.success = null
            this.$store.dispatch('password/sendPasswordResetEmail', { email })
                .then(success => {
                    this.loading = false
                    this.success = success
                }
                )
                .catch(error=> {
                    this.loading = false
                    this.error = error
                }
                )
        },

        clearEmailStatus(){
            this.$store.dispatch('password/clearEmailStatus')
        }
    }
};
</script>

1 个答案:

答案 0 :(得分:1)

我看到您正在validate_email中验证电子邮件,但看不到它在任何地方被调用。

serializer.is_valid(raise_exception=True)将不会呼叫您的validate_email。它将仅检查请求模式是否与PasswordResetSerializer中定义的模式匹配,即是否存在email,并且它是有效的电子邮件字段。请注意,它不会检查传递的电子邮件是否在您的数据库email = serializers.EmailField()中。

您可以做的是

1:将validate_email重命名为validate。可以通过.is_valid()来确保进行调用。

OR

2:将您自己的(可重复使用的)自定义验证器编写为ExistingEmailValidator,并在序列化程序中将其用作email = serializers.EmailField(validators=[ExistingEmailValidator])

@deconstructible
class ExistingEmailValidator(EmailValidator):
    message = 'Sorry. No user found with that email address.'

    def __init__(self, message=None, **kwargs):
        super().__init__(**kwargs)
        if message is not None:
            self.message = message

    def __call__(self, value, *args, **kwargs):
        if not User.objects.filter(email=value).exists():
            raise ValidationError('Sorry.No user found with that email address.')

如果未在其他任何地方使用它,则首选第一种方法。如果您想在其他地方重用此验证器,请选择第二个。