2013-08-23 26 views
91

करने के लिए अतिरिक्त क्षेत्र जोड़ने मैं धारावाहिक जा करने के लिए एक मॉडल को क्रमानुसार, लेकिन उस मॉडल उदाहरण पर कुछ डेटाबेस लुकअप कर की आवश्यकता है एक अतिरिक्त क्षेत्र को शामिल करना चाहते हैं:Django बाकी फ्रेमवर्क: ModelSerializer

class FooSerializer(serializers.ModelSerializer): 
    my_field = ... # result of some database queries on the input Foo object 
    class Meta: 
     model = Foo 
     fields = ('id', 'name', 'myfield') 

क्या है ऐसा करने का सही तरीका? मैं देखता हूं कि you can pass in extra "context" धारावाहिक के लिए, एक संदर्भ शब्दकोश में अतिरिक्त फ़ील्ड में पास करने का सही उत्तर है? उस दृष्टिकोण के साथ, मुझे आवश्यक फ़ील्ड प्राप्त करने का तर्क धारावाहिक परिभाषा के साथ स्वयं निहित नहीं होगा, जो कि आदर्श है क्योंकि हर धारावाहिक उदाहरण को my_field की आवश्यकता होगी। डीआरएफ धारावाहिक दस्तावेजों में कहीं और says "अतिरिक्त फ़ील्ड किसी भी संपत्ति के अनुरूप हो सकते हैं या मॉडल पर कॉल करने योग्य"। क्या अतिरिक्त फ़ील्ड मैं किस बारे में बात कर रहा हूं? क्या मुझे Foo की मॉडल परिभाषा में एक फ़ंक्शन परिभाषित करना चाहिए जो my_field मान देता है, और serializer में मैं my_field को उस कॉल करने योग्य को हुक करता हूं? वह किस तरह का दिखता है?

अग्रिम धन्यवाद, यदि आवश्यक हो तो प्रश्न को स्पष्ट करने में प्रसन्नता हो रही है।

उत्तर

158

मुझे लगता है कि SerializerMethodField आप जो खोज रहे हैं:

class FooSerializer(serializers.ModelSerializer): 
    my_field = serializers.SerializerMethodField('is_named_bar') 

    def is_named_bar(self, foo): 
     return foo.name == "bar" 

    class Meta: 
    model = Foo 
    fields = ('id', 'name', 'my_field') 

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

+0

+1 बढ़ाएं, क्या यह कस्टमसेरियलाइज़र के लिए भी काम करेगा? –

+12

क्या ऐसे क्षेत्रों में सत्यापन जोड़ना संभव है? मेरा सवाल है: कस्टम POST मानों को कैसे स्वीकार किया जाए जिन्हें post_save() हैंडलर में मान्य और संसाधित किया जा सकता है? – Alp

+7

ध्यान दें कि SerializerMethodField केवल पढ़ने के लिए है, इसलिए यह आने वाली पोस्ट/पुट/पैच के लिए काम नहीं करेगा। –

29

आप अपनी मॉडल विधि को संपत्ति में बदल सकते हैं और इस दृष्टिकोण के साथ धारावाहिक में इसका उपयोग कर सकते हैं।

संपादित करें: बाकी ढांचे के हालिया संस्करण के साथ (मैं 3.3.3 करने की कोशिश की), तो आप संपत्ति को बदलने की जरूरत नहीं है। मॉडल विधि बस ठीक काम करेगा।

+0

धन्यवाद @ वासिल! मैं Django मॉडल में गुणों के उपयोग से परिचित नहीं हूं, और इसका अर्थ क्या है इसका अच्छा स्पष्टीकरण नहीं मिल रहा है। क्या तुम समझा सकते हो? यहां @property सजावट का मुद्दा क्या है? – Neil

+2

इसका मतलब है कि आप इस विधि को किसी संपत्ति की तरह कॉल कर सकते हैं: i.e. 'variable = model_instance.my_field' सजावटी के बिना' variable = model_instance.my_field() 'के समान परिणाम देता है। भी: http://stackoverflow.com/a/6618176/2198571 –

+0

यह कम से कम Django 1.5.1/djangorestframework == 2.3.10 में काम नहीं कर रहा है। ModelSerializer को "फ़ील्ड" मेटा विशेषता में स्पष्ट रूप से संदर्भित होने पर भी प्रोपरी नहीं मिल रही है। – ygneo

8

एक समान प्रश्न (here) करने के लिए मेरा जवाब उपयोगी हो सकता है।

आप एक मॉडल विधि निम्नलिखित तरीके से परिभाषित किया गया है:

class MyModel(models.Model): 
    ... 

    def model_method(self): 
     return "some_calculated_result" 

तुम इतनी तरह अपने serializer बुला कहा विधि का परिणाम जोड़ सकते हैं:

class MyModelSerializer(serializers.ModelSerializer): 
    model_method_field = serializers.CharField(source='model_method') 

पी.एस. के बाद से कस्टम फ़ील्ड वास्तव में अपने मॉडल में एक क्षेत्र नहीं है, आप आमतौर पर बनाने के लिए यह केवल पढ़ने के लिए है, इसलिए की तरह चाहता हूँ:

class Meta: 
    model = MyModel 
    read_only_fields = (
     'model_method_field', 
     ) 
7
Django बाकी फ्रेमवर्क के पिछले संस्करण के साथ

, आप एक बनाने की जरूरत उस फ़ील्ड के नाम के साथ अपने मॉडल में विधि जिसे आप जोड़ना चाहते हैं। @property और source='field' की कोई आवश्यकता नहीं है।

class Foo(models.Model): 
    . . . 
    def foo(self): 
     return 'stuff' 
    . . . 

class FooSerializer(ModelSerializer): 
    foo = serializers.ReadOnlyField() 

    class Meta: 
     model = Foo 
     fields = ('foo',) 
संबंधित मुद्दे