2014-06-04 10 views
9

मुझे यह जानकारी दस्तावेज़ों या इंटरव्यू पर नहीं मिल सकती है।
नवीनतम Django-आराम-ढांचे, Django 1.6.5django-rest-framework, बहुमुखी मॉडल विरासत, मॉडलसेरियलाइजर्स और नेस्टेड धारावाहिक

एक एक ModelSerializer कि एक नेस्टेड serializers जहां नेस्टेड मॉडल multitable वंशानुक्रम का उपयोग कार्यान्वित किया जाता है संभाल कर सकते हैं कैसे बना सकता है?

उदा।

##### MODELS 
class OtherModel(Models.Model): 
    stuff = models.CharField(max_length=255) 

class MyBaseModel(models.Model): 
    whaddup = models.CharField(max_length=255) 
    other_model = models.ForeignKey(OtherModel) 

class ModelA(MyBaseModel): 
    attr_a = models.CharField(max_length=255) 

class ModelB(MyBaseModel): 
    attr_b = models.CharField(max_length=255) 


#### SERIALIZERS 
class MyBaseModelSerializer(serializers.ModelSerializer): 
    class Meta: 
     model=MyBaseModel 

class OtherModelSerializer(serializer.ModelSerializer): 
    mybasemodel_set = MyBaseModelSerializer(many=True) 

    class Meta: 
     model = OtherModel 

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

यदि यह महत्वपूर्ण है, तो मैं django.model_utils और उत्तराधिकारी का उपयोग भी कर रहा हूं, इसलिए मैं एक क्वेरीसेट पुनर्प्राप्त कर सकता हूं जहां प्रत्येक उदाहरण पहले से ही उपयुक्त उप-वर्ग का उदाहरण है।

धन्यवाद

उत्तर

4

मैं एक कस्टम relatedfield

class MyBaseModelField(serializers.RelatedField): 
    def to_native(self, value): 
     if isinstance(value, ModelA): 
      a_s = ModelASerializer(instance=value) 
      return a_s.data 
     if isinstance(value, ModelB): 
      b_s = ModelBSerializer(instance=value) 
      return b_s.data 

     raise NotImplementedError 


class OtherModelSerializer(serializer.ModelSerializer): 
    mybasemodel_set = MyBaseModelField(many=True) 

    class Meta: 
     model = OtherModel 
     fields = # make sure we manually include the reverse relation (mybasemodel_set,) 
बनाकर ऐसा कर पा रहा था

मैं चिंता है कि प्रत्येक वस्तु के लिए एक Serializer instanting रिवर्स संबंध क्वेरीसमूह महंगा तो मैं सोच रहा हूँ है की क्या ज़रूरत है अगर ऐसा करने का एक बेहतर तरीका है।

एक और दृष्टिकोण मैं करने की कोशिश की गतिशील __init__ के अंदर MyBaseModelSerializer पर मॉडल क्षेत्र बदल रहा था, लेकिन मैं इस मुद्दे को यहाँ वर्णित में भाग:
django rest framework nested modelserializer

+1

http://www.django-rest-framework.org/topics/3.0-announcement/#changes-to-the-custom-field-api –

+1

क्या आपको अभी तक एक बेहतर समाधान मिला है? – eugene

0

मैं एक समाधान है कि के लिए अलग serializer उपवर्गों शामिल उपयोग करने का प्रयास कर रहा हूँ अलग मॉडल उपवर्गों:

class MyBaseModelSerializer(serializers.ModelSerializer): 

    @staticmethod 
    def _get_alt_class(cls, args, kwargs): 
     if (cls != MyBaseModel): 
      # we're instantiating a subclass already, use that class 
      return cls 

     # < logic to choose an alternative class to use > 
     # in my case, I'm inspecting kwargs["data"] to make a decision 
     # alt_cls = SomeSubClass 

     return alt_cls 

    def __new__(cls, *args, **kwargs): 
     alt_cls = MyBaseModel.get_alt_class(cls, args, kwargs) 
     return super(MyBaseModel, alt_cls).__new__(alt_cls, *args, **kwargs) 

    class Meta: 
     model=MyBaseModel 

class ModelASerializer(MyBaseModelSerializer): 
    class Meta: 
     model=ModelA 

class ModelBSerializer(MyBaseModelSerializer): 
    class Meta: 
     model=ModelB 

है यही कारण है कि, जब आप कोशिश करते हैं और प्रकार MyBaseModelSerializer की एक वस्तु का दृष्टांत, आप वास्तव में ऊपर उपवर्गों, जो क्रमानुसार में से एक का एक उद्देश्य के साथ मेरे लिए खत्म हो (और महत्वपूर्ण, deseri alize) सही ढंग से।

मैंने अभी इसका उपयोग शुरू कर दिया है, इसलिए यह संभव है कि ऐसी समस्याएं हैं जिन्हें मैंने अभी तक नहीं चलाया है।

+0

get_alt_class को एक staticmethod क्यों बना रहा है जिससे आप सीएल पास कर रहे हैं? कोई कारण ? –

6

मैंने इस मुद्दे को थोड़ा अलग तरीके से हल किया है।

का उपयोग करना:

  • डीआरएफ 3.5.x
  • Django मॉडल-utils 2.5.x

मेरे models.py देखो इस तरह:

class Person(models.Model): 
    first_name = models.CharField(max_length=40, blank=False, null=False) 
    middle_name = models.CharField(max_length=80, blank=True, null=True) 
    last_name = models.CharField(max_length=80, blank=False, null=False) 
    family = models.ForeignKey(Family, blank=True, null=True) 


class Clergy(Person): 
    category = models.IntegerField(choices=CATEGORY, blank=True, null=True) 
    external = models.NullBooleanField(default=False, null=True) 
    clergy_status = models.ForeignKey(ClergyStatus, related_name="%(class)s_status", blank=True, null=True) 


class Religious(Person): 
    religious_order = models.ForeignKey(ReligiousOrder, blank=True, null=True) 
    major_superior = models.ForeignKey(Person, blank=True, null=True, related_name="%(class)s_superior") 


class ReligiousOrder(models.Model): 
    name = models.CharField(max_length=255, blank=False, null=False) 
    initials = models.CharField(max_length=20, blank=False, null=False) 


class ClergyStatus(models.Model): 
    display_name = models.CharField(max_length=255, blank=True, null=True) 
    description = models.CharField(max_length=255, blank=True, null=True) 

मूल रूप से - आधार मॉडल "व्यक्ति" मॉडल है - और एक व्यक्ति या तो पादरी, धार्मिक, या न ही हो सकता है और बस एक हो सकता है "व्यक्ति"। जबकि Person के उत्तराधिकारी के विशेष संबंध भी हैं।

मेरी views.py में मैं बहुत की तरह क्वेरीसमूह में उपवर्गों "इंजेक्षन" करने के लिए एक mixin का उपयोग: मैं जहां "आधार" PersonListSerializer घोषित

class PersonSubClassFieldsMixin(object): 

    def get_queryset(self): 
     return Person.objects.select_subclasses() 

class RetrievePersonAPIView(PersonSubClassFieldsMixin, generics.RetrieveDestroyAPIView): 
    serializer_class = PersonListSerializer 
    ... 

और फिर असली "undry" भाग serializers.py में आता है, लेकिन इसलिए जैसे उदाहरण के प्रकार के आधार पर विशेष serailzers वापस जाने के लिए to_representation विधि ओवरराइड:

class PersonListSerializer(serializers.ModelSerializer): 

    def to_representation(self, instance): 
     if isinstance(instance, Clergy): 
      return ClergySerializer(instance=instance).data 
     elif isinstance(instance, Religious): 
      return ReligiousSerializer(instance=instance).data 
     else: 
      return LaySerializer(instance=instance).data 

    class Meta: 
     model = Person 
     fields = '__all__' 


class ReligiousSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Religious 
     fields = '__all__' 
     depth = 2 


class LaySerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Person 
     fields = '__all__' 


class ClergySerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Clergy 
     fields = '__all__' 
     depth = 2 

"स्विच" मुख्य serializer की to_representation विधि में क्या होता है (PersonListSerializer)। यह इंस्टेंस प्रकार को देखता है, और उसके बाद आवश्यक धारावाहिक "इंजेक्ट करता है"। चूंकि Clergy, Religious सभी Person से Person वापस प्राप्त कर रहे हैं जो Clergy सदस्य भी हैं, सभी Person फ़ील्ड और सभी Clergy फ़ील्ड लौटाते हैं। Religious के लिए ही चला जाता है। और यदि Person न तो Clergy या Religious है - आधार मॉडल फ़ील्ड केवल लौटाए जाते हैं।

सुनिश्चित नहीं है कि यह उचित दृष्टिकोण है - लेकिन यह बहुत लचीला लगता है, और मेरे उपयोगकेस फिट बैठता है। ध्यान दें कि मैं अलग-अलग विचार/धारावाहिकों के माध्यम से Person को सहेज/अपडेट/बना सकता हूं - इसलिए मुझे इस प्रकार के सेटअप के बारे में चिंता करने की ज़रूरत नहीं है।

संबंधित मुद्दे