2016-04-04 12 views
5

के साथ django पासवर्ड सत्यापनकर्ताओं को एकीकृत करें मैं dzango आराम फ्रेमवर्क serializers के साथ django validators 1.9 को एकीकृत करने की कोशिश कर रहा हूं। लेकिन serialized 'उपयोगकर्ता' (django आराम ढांचे का) django मान्यताओं के साथ संगत नहीं है।django rest framework validate_password

यहाँ serializers.py

import django.contrib.auth.password_validation as validators 
from rest_framework import serializers 

    class RegisterUserSerializer(serializers.ModelSerializer): 

     password = serializers.CharField(style={'input_type': 'password'}, write_only=True) 

     class Meta: 
      model = User 
      fields = ('id', 'username', 'email, 'password') 

     def validate_password(self, data): 
      validators.validate_password(password=data, user=User) 
      return data 

     def create(self, validated_data): 
      user = User.objects.create_user(**validated_data) 
      user.is_active = False 
      user.save() 
      return user 

मैं MinimumLengthValidator और NumericPasswordValidator सही पाने के लिए है क्योंकि दोनों समारोह सत्यापित करें सत्यापित करने में 'उपयोगकर्ता का उपयोग नहीं करते कामयाब रहे है।

def validate(self, password, user=None): 
     if password.isdigit(): 
      raise ValidationError(
       _("This password is entirely numeric."), 
       code='password_entirely_numeric', 
      ) 

UserAttributeSimilarityValidator जैसे अन्य प्रमाणकों के लिए, समारोह ('उपयोगकर्ता को सत्यापित करने में एक और एक तर्क' उपयोगकर्ता 'का उपयोग करता है Django उपयोगकर्ता मॉडल है, अगर मैं: स्रोत कोड Django स्रोत कोड से here

अंश है मीटर गलत नहीं) Django स्रोत कोड से

अंश:

def validate(self, password, user=None): 
     if not user: 
      return 

     for attribute_name in self.user_attributes: 
      value = getattr(user, attribute_name, None) 

मैं serializ कैसे बदल सकता हूँ क्या django प्रमाणकों (UserAttributeSimilarityValidator) में एड उपयोगकर्ता Django स्रोत कोड से

अंश देख सकते हैं:

def validate(self, password, user=None): 
     if not user: 
      return 

     for attribute_name in self.user_attributes: 
      value = getattr(user, attribute_name, None) 
      if not value or not isinstance(value, string_types): 
       continue 

संपादित

Django बाकी फ्रेमवर्क Django के के सभी प्राप्त कर सकते हैं में निर्मित पासवर्ड सत्यापन (लेकिन यह एक हैक की तरह है)। यहाँ एक समस्या है:

validationError की तरह इस

[ValidationError ([ 'यह पासवर्ड बहुत छोटा है यह से कम 8 अक्षर में होना चाहिए।।']), ValidationError ([ 'यह पासवर्ड है पूरी तरह से संख्यात्मक। '])]

सत्यापन में फ़ील्ड नहीं है। Django बाकी ढांचे

{ 
    "non_field_errors": [ 
     "This password is too short. It must contain at least 8 characters.", 
     "This password is entirely numeric." 
    ] 
} 

रूप में देखते हैं मैं raise ValidationError

उत्तर

8

की तरह आप का उल्लेख एक क्षेत्र इंजेक्षन कर सकते हैं कैसे, जब आप को मान्य passwordUserAttributeSimilarityValidator सत्यापनकर्ता का उपयोग कर validate_password में विधि, आप user वस्तु नहीं है।

मेरा सुझाव है क्या कि बजाय क्षेत्र स्तरीय सत्यापन कर के, आप serializer पर validate विधि को लागू करने से object-level validation प्रदर्शन करेगा:

import sys 
from django.core import exceptions 
import django.contrib.auth.password_validation as validators 

class RegisterUserSerializer(serializers.ModelSerializer): 

    # rest of the code 

    def validate(self, data): 
     # here data has all the fields which have validated values 
     # so we can create a User instance out of it 
     user = User(**data) 

     # get the password from the data 
     password = data.get('password') 

     errors = dict() 
     try: 
      # validate the password and catch the exception 
      validators.validate_password(password=password, user=User) 

     # the exception raised here is different than serializers.ValidationError 
     except exceptions.ValidationError as e: 
      errors['password'] = list(e.messages) 

     if errors: 
      raise serializers.ValidationError(errors) 

     return super(RegisterUserSerializer, self).validate(data) 
+0

अपने कोड में कुछ टाइपो रहे हैं की जरूरत है। वैसे, आपका समाधान मान्य करने पर ठीक काम करता है लेकिन django आराम ढांचे को फ़ील्ड नाम नहीं मिल सकता है इसलिए non_field_errors ---> { "non_field_errors": [ "पासवर्ड ईमेल के समान ही है।", " यह पासवर्ड बहुत छोटा है। इसमें कम से कम 8 वर्ण होने चाहिए। " ] } – momokjaaaaa

+0

मैंने वास्तव में कोड का परीक्षण नहीं किया है, इसलिए यहां कुछ और टाइप हो सकते हैं लेकिन आपको इस कोड का सही उपयोग करने और परीक्षण करने से नहीं रोकना चाहिए। 'NON_FIELD_ERRORS' के बारे में मैंने अपना उत्तर अपडेट किया और अब उठाए गए त्रुटियों में उन त्रुटियों के लिए कुंजी के रूप में 'password' फ़ील्ड नाम होना चाहिए। – AKS

+0

ध्यान रखें कि '** डेटा' में आंशिक ('पैच') अपडेट करते समय उपयोगकर्ता ऑब्जेक्ट बनाने के लिए सभी आवश्यक फ़ील्ड शामिल नहीं हो सकते हैं। – faph

6

आप उपयोगकर्ता वस्तु self.instance के माध्यम से serializer वस्तु पर, तब भी जब तक पहुँच सकते हैं फील्ड-स्तरीय सत्यापन करना।इस तरह कुछ काम करना चाहिए:

from django.contrib.auth import password_validation 

def validate_password(self, value): 
    password_validation.validate_password(value, self.instance) 
    return value 
+0

यह केवल तभी उपलब्ध होगा यदि उपयोगकर्ता बनाया गया है, जो कोई नया उपयोगकर्ता पंजीकृत करने और पासवर्ड पूर्व-निर्माण को सत्यापित करते समय ऐसा नहीं होगा। – tbm

1

सीरियलाइज़र का उपयोग करें! validate_fieldname विधि है!

class UserSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = User 
     fields = (
      'id', 'username', 'password', 'first_name', 'last_name', 'email' 
     ) 
     extra_kwargs = { 
      'password': {'write_only': True}, 
      'username': {'read_only': True} 
     } 

    def validate_password(self, value): 
     try: 
      validate_password(value) 
     except ValidationError as exc: 
      raise serializers.ValidationError(str(exc)) 
     return value 

    def create(self, validated_data): 
     validated_data = self.check_for_unique_email(validated_data) 
     validated_data.setdefault('username', validated_data['email']) 
     user = super().create(validated_data) 
     user.set_password(validated_data['password']) 

     user.is_active = False 
     user.save() 
     return user 

    def update(self, instance, validated_data): 
     validated_data = self.check_for_unique_email(validated_data) 
     user = super().update(instance, validated_data) 
     if 'password' in validated_data: 
      user.set_password(validated_data['password']) 
      user.save() 
     return user 
0

नया उपयोगकर्ता (पंजीकरण) तो self.instance हो जाएगा कोई भी बनाने के समय, यह काम जब अपना पासवर्ड, पासवर्ड बदलें आराम कर रहे हैं या पासवर्ड के साथ उपयोगकर्ता डेटा को अद्यतन करने होंगे। लेकिन आप पासवर्ड की जांच करने के लिए अपने ईमेल या उपयोगकर्ता नाम के समान नहीं होना चाहिए चाहते हैं तो आप "SequenceMatcher" अपने सत्यापन में शामिल करने के लिए

data = self.get_initial() 
username = data.get("username") 
email = data.get("email") 
password = data.get("password") 
max_similarity = 0.7 
if SequenceMatcher(a=password.lower(), b=username.lower()).quick_ratio() > max_similarity: 
    raise serializers.ValidationError("The password is too similar to the username.") 
if SequenceMatcher(a=password.lower(), b=email.lower()).quick_ratio() > max_similarity: 
    raise serializers.ValidationError("The password is too similar to the email.")