2014-12-21 14 views
13

स्थितिDjango में अतिरिक्त Serializer फील्ड्स बाकी फ्रेमवर्क 3

मैं एक साधारण endpoint है कि एक उपयोगकर्ता के निर्माण के लिए अनुमति देता है बनाने रहा हूँ। मुझे ऐसे क्षेत्र की आवश्यकता है जो मेरे उपयोगकर्ता मॉडल में नहीं है (यानी, confirm_password)। मैं सत्यापन को चलाऊंगा जो इस क्षेत्र और मेरे मॉडल में मौजूद किसी अन्य फ़ील्ड की तुलना करता है, और फिर धारावाहिक में फिर से अतिरिक्त फ़ील्ड का उपयोग न करें।

समस्या

डीआरएफ संस्करण 3 इस पूरा करने के लिए प्रक्रिया बदल गया है, और मैं काफी क्या प्रलेखन मैं क्या सुझाव दे रहा है समझ में नहीं आता। प्रलेखन के लिए here देखें। समाधान पर

प्रयास

मैं एक UserSerializer कि इस तरह दिखता है बनाया है:

from django.contrib.auth import get_user_model 
from rest_framework import serializers 

class UserSerializer(serializers.ModelSerializer): 
    confirm_password = serializers.CharField(allow_blank=False) 

    def validate(self, data): 
     """ 
     Checks to be sure that the received password and confirm_password 
     fields are exactly the same 
     """ 
     if data['password'] != data.pop('confirm_password'): 
      raise serializers.ValidationError("Passwords do not match") 
     return data 

    def create(self, validated_data): 
     """ 
     Creates the user if validation succeeds 
     """ 
     password = validated_data.pop('password', None) 
     user = self.Meta.model(**validated_data) 
     user.set_password(password) 
     user.save() 
     return user 

    class Meta: 
     # returns the proper auth model 
     model = get_user_model() 
     # fields that will be deserialized 
     fields = ['password', 'confirm_password', 
        'username', 'first_name', 'last_name', 'email'] 
     # fields that will be serialized only 
     read_only_fields = ['is_staff', 'is_superuser'] 
     # fields that will be deserialized only 
     write_only_fields = ['password' 'confirm_password'] 

मुझे उम्मीद थी कि validate में confirm_password पॉपिंग अपनी समस्याओं का ख्याल रखना होगा, लेकिन मैं तो बस मिल निम्नलिखित:

KeyError मिला जब एक प्राप्त करने का प्रयास किया गया serializer UserSerializer पर फ़ील्ड confirm_password के लिए मान। serializer क्षेत्र गलत तरीके से और न नाम दिया जा सकता OrderedDict उदाहरण

+0

बस एक सिर ऊपर है, यह आम है कि ज्यादातर लोगों को डाल करने के लिए के लिए धारावाहिक के शीर्ष पर 'मेटा' वर्ग, क्योंकि इसमें अधिकतर जानकारी शामिल है जिसे आप आम तौर पर ढूंढ रहे हैं। –

+0

आह, यह समझ में आता है। मैं इसकी सराहना करता हूं! – nmagerko

उत्तर

18

आप एक लेख केवल क्षेत्र के लिए देख रहे हैं पर कोई विशेषता या कुंजी के मिलान, के रूप में मैं तुम्हें में पासवर्ड की पुष्टि प्रदर्शित करने के लिए नहीं चाहते हैं यह सोचते हैं रहा हूँ एपीआई Django REST फ्रेमवर्क ने write_only पैरामीटर को read_only पैरामीटर के पूरक के लिए 2.3.x टाइमलाइन में पेश किया, इसलिए एक बार अपडेट होने पर एकमात्र समय सत्यापन चलती है। write_only_fields मेटा संपत्ति एक ही समय में जोड़ दी गई थी, लेकिन यह समझना महत्वपूर्ण है कि इनमें से दोनों कैसे काम करते हैं।

write_only_fields मेटा संपत्ति स्वतः write_only संपत्ति एक क्षेत्र के लिए जब यह स्वचालित रूप से बनाया जाता है, की तरह एक password क्षेत्र के लिए एक User मॉडल पर जोड़ देगा। यह ऐसा कोई भी फ़ील्ड नहीं है जो मॉडल पर नहीं है, या फ़ील्ड जिन्हें धारावाहिक पर स्पष्ट रूप से निर्दिष्ट किया गया है। आपके मामले में, आप अपने serializer पर confirm_password फ़ील्ड को स्पष्ट रूप से निर्दिष्ट कर रहे हैं, यही कारण है कि यह काम नहीं कर रहा है।

गॉट KeyError जब serializer UserSerializer पर क्षेत्र confirm_password के लिए एक मूल्य प्राप्त करने का प्रयास। serializer क्षेत्र गलत तरीके से और न नाम दिया जा सकता, OrderedDict उदाहरण

इस बनाए गए उपयोगकर्ता के फिर से क्रमांकन के दौरान उठाया है पर किसी भी विशेषता या कुंजी का मिलान जब वह अपने confirm_password क्षेत्र क्रमानुसार करने की कोशिश कर रहा है। क्योंकि यह User मॉडल पर फ़ील्ड नहीं ढूंढ सकता है, यह इस त्रुटि को ट्रिगर करता है जो समस्या को समझाने का प्रयास करता है। दुर्भाग्यवश क्योंकि यह नया उपयोगकर्ता पर है, तो यह आपको User उदाहरण के बजाय OrderedDict उदाहरण को भ्रमित रूप से देखने के लिए कहता है।

class UserSerializer(serializers.ModelSerializer): 
    confirm_password = serializers.CharField(allow_blank=False, write_only=True) 

आप स्पष्ट रूप से serializer मैदान पर write_only निर्दिष्ट करें, और अपने write_only_fields से क्षेत्र को निकालते हैं, तो आप व्यवहार आपके उम्मीद कर रहे हैं देखना चाहिए।

आप इस link

0

नेस्टेड serializer कार्यान्वयन का प्रतिनिधित्व मॉडल के लिए इसके अलावा उपयोगी है, जब जड़ मॉडल सीधे नहीं है आप उपयोग करना चाहते क्षेत्रों के लिए पहुँच पर इस बारे में दस्तावेज़ प्राप्त कर सकते हैं। आप @vyscond धन्यवाद;) FYI करें यहाँ मेरे मामले है:

models.py

class Company(models.Model): 
    permission_classes = (
     IsCompanyMember, 
    ) 

    name = models.CharField(
     unique=True, 
     max_length=100, 
     verbose_name='company name', 
     null=False 
    ) 
class Profile(models.Model): 

    company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True) 
    user = models.OneToOneField(User, on_delete=models.CASCADE) 
    is_company_admin = models.BooleanField(default=False, null=False) 
    is_email_validated = models.BooleanField(default=False, null=False) 
    is_approved_by_company_admin = models.BooleanField(default=False, null=False) 

serializer.py

class CompanySerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Company 
     fields = ('name',) 

class CustomUserRegistrationSerializer(serializers.ModelSerializer): 
    password = serializers.CharField(style={'input_type': 'password'}, 
           write_only=True, 
           validators=settings.get('PASSWORD_VALIDATORS')) 

    company = CompanySerializer(allow_null=False, required=True,write_only=True) 

    class Meta: 
     model = User 
     fields = ('username', 
        'email', 
        'password', 
        'company', 
        'first_name', 
        'last_name') 
संबंधित मुद्दे