Django रीस्ट फ्रेमवर्क: ModelSerializer में अतिरिक्त फ़ील्ड जोड़ रहा है


147

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

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

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

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

जवाबों:


224

मुझे लगता है कि 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


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

20
ध्यान दें कि SerializerMethodField केवल-पढ़ने के लिए है, इसलिए यह आने वाले POST / PUT / PATCH के लिए काम नहीं करेगा।
स्कॉट ए

24
DRF 3 में, इसे बदल दिया जाता है field_name = serializers.SerializerMethodField()औरdef get_field_name(self, obj):
रासायनिक प्रोग्रामर

1
क्या fooजब डीईएफ़ एक SerializerMethodField? जब CreateAPIView का उपयोग करते हैं, तो क्या foo संग्रहीत किया गया है तो is_onym_bar () विधि का उपयोग कर सकते हैं?
244boy

तो, इस उत्तर के आधार पर, यदि आप अपने धारावाहिक के लिए 12 अतिरिक्त क्षेत्र कहना चाहते हैं, तो आपको प्रत्येक फ़ील्ड के लिए 12 विशिष्ट तरीकों को परिभाषित करने की आवश्यकता है, जो सिर्फ foo.field_custom लौटाता है?
AlxVallejo

41

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

class Foo(models.Model):
    . . .
    @property
    def my_field(self):
        return stuff
    . . .

class FooSerializer(ModelSerializer):
    my_field = serializers.ReadOnlyField(source='my_field')

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

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


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

2
इसका मतलब है कि आप इस तरीके को संपत्ति की तरह कह सकते हैं: यानी बिना सज्जाकार variable = model_instance.my_fieldके समान परिणाम देता है variable = model_instance.my_field()। यह भी: stackoverflow.com/a/6618176/2198571
Wasil Sergejczyk

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

9
आपको धारावाहिक में फ़ील्ड जोड़ने की आवश्यकता है क्योंकि यह कोई वास्तविक मोडफ़िल्ड नहीं है: my_field = serializers.Field (source = 'my_field')
Marius

2
source='my_field' अब और आवश्यकता नहीं है और एक अपवाद
बढ़ाएँ

13

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',)

क्या होगा यदि मैं requestडीईएफ फू (स्व) के अंदर वस्तु रखना चाहता हूं जो फू के मूल्य को संशोधित कर सकता है? (उदाहरण के लिए एक
निवेदन पर

1
क्या होगा अगर फू का मूल्य अनुरोध से आ रहा है?
saran3h

11

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

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

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

आप अपने क्रमबद्ध तरीके से कॉलिंग विधि के परिणाम को इस तरह जोड़ सकते हैं:

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

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

class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )

10

यदि आप अपने अतिरिक्त क्षेत्र पर पढ़ना और लिखना चाहते हैं, तो आप एक नए कस्टम धारावाहिक का उपयोग कर सकते हैं, जो कि धारावाहिकों का विस्तार करता है।

class ExtraFieldSerializer(serializers.Serializer):
    def to_representation(self, instance): 
        # this would have the same as body as in a SerializerMethodField
        return 'my logic here'

    def to_internal_value(self, data):
        # This must return a dictionary that will be used to
        # update the caller's validation data, i.e. if the result
        # produced should just be set back into the field that this
        # serializer is set to, return the following:
        return {
          self.field_name: 'Any python object made with data: %s' % data
        }

class MyModelSerializer(serializers.ModelSerializer):
    my_extra_field = ExtraFieldSerializer(source='*')

    class Meta:
        model = MyModel
        fields = ['id', 'my_extra_field']

मैं कुछ कस्टम तर्क के साथ संबंधित नेस्टेड फ़ील्ड में इसका उपयोग करता हूं


2

यह मेरे लिए काम करता है । अगर हम सिर्फ ModelSerializer में एक अतिरिक्त फ़ील्ड जोड़ना चाहते हैं, तो हम इसे नीचे की तरह कर सकते हैं और साथ ही फ़ील्ड को लुकअप की कुछ गणनाओं के बाद कुछ वैल असाइन किया जा सकता है। या किसी मामले में अगर हम एपीआई प्रतिक्रिया में पैरामीटर भेजना चाहते हैं।

Model.py में

class Foo(models.Model):
    """Model Foo"""
    name = models.CharField(max_length=30, help_text="Customer Name")



   **

Serializer.py में

**

class FooSerializer(serializers.ModelSerializer):
    retrieved_time = serializers.SerializerMethodField()

    @classmethod
    def get_retrieved_time(self, object):
        """getter method to add field retrieved_time"""
        return None

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

**

आशा है कि यह किसी की मदद कर सकता है

**


0

जैसा कि केमिकल प्रोग्रामर ने इस टिप्पणी में कहा , नवीनतम डीआरएफ में आप इसे इस तरह से कर सकते हैं:

class FooSerializer(serializers.ModelSerializer):
    extra_field = serializers.SerializerMethodField()

    def get_extra_field(self, foo_instance):
        return foo_instance.a + foo_instance.b

    class Meta:
        model = Foo
        fields = ('extra_field', ...)

DRF डॉक्स स्रोत

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.