Django रेस्ट फ्रेमवर्क में प्रतिक्रियाओं में मध्यस्थ (मॉडल के माध्यम से) शामिल करें


110

मेरे पास m2m / मॉडल के माध्यम से निपटने और django बाकी ढांचे में उनकी प्रस्तुति के बारे में एक सवाल है। आइए एक उत्कृष्ट उदाहरण लें:

models.py:

from django.db import models

class Member(models.Model):
    name = models.CharField(max_length = 20)
    groups = models.ManyToManyField('Group', through = 'Membership')

class Group(models.Model):
    name = models.CharField(max_length = 20)

class Membership(models.Model):
    member = models.ForeignKey('Member')
    group = models.ForeignKey('Group')
    join_date = models.DateTimeField()

serializers.py:

imports...

class MemberSerializer(ModelSerializer):
    class Meta:
        model = Member

class GroupSerializer(ModelSerializer):
    class Meta:
        model = Group

views.py:

imports...

class MemberViewSet(ModelViewSet):
    queryset = Member.objects.all()
    serializer_class = MemberSerializer

class GroupViewSet(ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

जब सदस्य का एक उदाहरण मिलता है, तो मैं सफलतापूर्वक सदस्य के सभी क्षेत्रों और इसके समूहों को प्राप्त करता हूं - हालांकि मुझे केवल सदस्यों के विवरण मिलते हैं, बिना अतिरिक्त विवरण के जो सदस्यता मॉडल से आता है।

दूसरे शब्दों में, मुझे प्राप्त होने की उम्मीद है:

{
   'id' : 2,
   'name' : 'some member',
   'groups' : [
      {
         'id' : 55,
         'name' : 'group 1'
         'join_date' : 34151564
      },
      {
         'id' : 56,
         'name' : 'group 2'
         'join_date' : 11200299
      }
   ]
}

Join_date पर ध्यान दें ।

मैंने ओह, इतने सारे समाधानों की कोशिश की है, जिसमें निश्चित रूप से इसके बारे में Django रेस्ट-फ्रेमवर्क आधिकारिक पेज शामिल है और कोई भी इसके बारे में उचित सादा जवाब नहीं देता है - मुझे इन अतिरिक्त क्षेत्रों को शामिल करने के लिए क्या करने की आवश्यकता है? मैंने इसे django-tastypie के साथ अधिक सीधे-आगे पाया, लेकिन कुछ अन्य समस्याएं थीं और बाकी ढांचे को प्राथमिकता दी।


क्या eugene-yeo.me/2012/12/4/… मदद करेगा?
कार्तिकार

8
यह स्वादिष्ट पाई के लिए है, मैं Django रेस्ट फ्रेमवर्क के साथ काम कर रहा हूं।
mllm

जवाबों:


139

कैसा रहेगा.....

अपने MemberSerializer पर, इस तरह एक क्षेत्र को परिभाषित करें:

groups = MembershipSerializer(source='membership_set', many=True)

और फिर अपनी सदस्यता के लिए आप इसे बना सकते हैं:

class MembershipSerializer(serializers.HyperlinkedModelSerializer):

    id = serializers.Field(source='group.id')
    name = serializers.Field(source='group.name')

    class Meta:
        model = Membership

        fields = ('id', 'name', 'join_date', )

यह एक क्रमबद्ध मूल्य बनाने के समग्र प्रभाव है, समूह, कि इसके स्रोत के रूप में सदस्यता आप चाहते हैं, और फिर यह बिट्स आप प्रदर्शित करना चाहते हैं बाहर खींचने के लिए एक कस्टम serializer का उपयोग करता है।

EDIT: जैसा कि @bryanph ने टिप्पणी की थी, serializers.fieldउसका नाम बदलकर serializers.ReadOnlyFieldDRF 3.0 कर दिया गया था , इसलिए इसे पढ़ना चाहिए:

class MembershipSerializer(serializers.HyperlinkedModelSerializer):

    id = serializers.ReadOnlyField(source='group.id')
    name = serializers.ReadOnlyField(source='group.name')

    class Meta:
        model = Membership

        fields = ('id', 'name', 'join_date', )

किसी भी आधुनिक कार्यान्वयन के लिए


2
fyi, मैंने इसके कई प्रकार आज़माए हैं और मुझे यह काम नहीं मिल रहा है। यह आधिकारिक डॉक्स में नहीं है? सदस्यता_सेट को कहां परिभाषित किया गया है?
मिट्टी

3
membership_setसदस्य के लिए डिफ़ॉल्ट संबंधित नाम है -> सदस्यता
dustinfarris

मेरे लिए चाल का हिस्सा "सदस्यता_सेट" नाम की खोज कर रहा था। मेरे पास कोई स्पष्ट "संबंधित" नाम वाला एक मॉडल था, इसलिए मुझे Django पर कई से डॉक्स पढ़कर, इसके नाम का अनुमान लगाना पड़ा ।
माईनो

यह महान काम करता है, संकेत के लिए धन्यवाद। मुझे लगता है कि हालांकि इस मामले में डीआरएफ कुछ हद तक उल्टा है क्योंकि क्लास मेंबर पहले से ही ग्रुप कहे जाने वाले एम 2 एम फील्ड को परिभाषित करता है और यह समाधान सीरियल मॉडल के माध्यम से रिवर्स रिलेशनशिप को इंगित करने के लिए मजबूर करके फील्ड को ओवरराइड करता है। मैं डीआरएफ कार्यान्वयन विवरणों में बहुत अधिक नहीं हूं, लेकिन शायद मॉडल आत्मनिरीक्षण के साथ यह स्वचालित रूप से सौंपा जा सकता है। सिर्फ कुछ सोचा के लिए भोजन :)
gru

किसी भी मामले में आप हमें अपडेट कर सकते हैं कि क्या यह डीआरएफ के नवीनतम संस्करण के साथ काम करता है? या कम से कम बताएं कि आप किस संस्करण का उपयोग कर रहे थे? मैं फील्ड मॉडल के माध्यम से वापस आने के लिए डीआरएफ नहीं बना सकता - यह हमेशा मूल संबंध (सदस्यता के बजाय - यह हमेशा समूह समूह) के साथ समाप्त होता है।
एंड्री सिज़ोव

18

मैं इस समस्या का सामना कर रहा था और मेरा समाधान (DRF 3.6 का उपयोग करके) ऑब्जेक्ट पर SerializerMethodField का उपयोग करना था और स्पष्ट रूप से सदस्यता तालिका को इस तरह क्वेरी करना था:

class MembershipSerializer(serializers.ModelSerializer):
    """Used as a nested serializer by MemberSerializer"""
    class Meta:
        model = Membership
        fields = ('id','group','join_date')

class MemberSerializer(serializers.ModelSerializer):
    groups = serializers.SerializerMethodField()

    class Meta:
        model = Member
        fields = ('id','name','groups')

    def get_groups(self, obj):
        "obj is a Member instance. Returns list of dicts"""
        qset = Membership.objects.filter(member=obj)
        return [MembershipSerializer(m).data for m in qset]

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


-4

नोट: एक सॉफ्टवेयर इंजीनियर के रूप में, मुझे आर्किटेक्चर का उपयोग करना पसंद है और मैंने डेवलपमेंट के लिए लेयर्ड अप्रोच पर गहराई से काम किया है, इसलिए मुझे इसका जवाब टियर्स के साथ देना होगा।

जैसा कि मैंने इस मुद्दे को समझा, यहाँ समाधान मॉडल थिंकपैड है

class Member(models.Model):
    member_id = models.AutoField(primary_key=True)
    member_name = models.CharField(max_length = 

class Group(models.Model):
    group_id = models.AutoField(primary_key=True)
    group_name = models.CharField(max_length = 20)
    fk_member_id = models.ForeignKey('Member', models.DO_NOTHING, 
                             db_column='fk_member_id', blank=True, null=True)

class Membership(models.Model):
    membershipid = models.AutoField(primary_key=True)
    fk_group_id = models.ForeignKey('Group', models.DO_NOTHING, 
                             db_column='fk_member_id', blank=True, null=True)
    join_date = models.DateTimeField()

serializers.py

import serializer

class AllSerializer(serializer.Serializer):
    group_id = serializer.IntegerField()
    group_name = serializer.CharField(max_length = 20)
    join_date = serializer.DateTimeField()

CustomModels.py

imports...

    class AllDataModel():
        group_id = ""
        group_name = ""
        join_date = ""

BusinessLogic.py

imports ....
class getdata(memberid):
    alldataDict = {}
    dto = []
    Member = models.Members.objects.get(member_id=memberid) #or use filter for Name
    alldataDict["MemberId"] = Member.member_id
    alldataDict["MemberName"] = Member.member_name
    Groups = models.Group.objects.filter(fk_member_id=Member)
    for item in Groups:
        Custommodel = CustomModels.AllDataModel()
        Custommodel.group_id = item.group_id
        Custommodel.group_name = item.group_name
        Membership = models.Membership.objects.get(fk_group_id=item.group_id)
        Custommodel.join_date = Membership.join_date
        dto.append(Custommodel)
    serializer = AllSerializer(dto,many=True)
    alldataDict.update(serializer.data)
    return alldataDict

आपको तकनीकी रूप से, DataAccessLayer के लिए अनुरोध पारित करना होगा, जो डेटा एक्सेस लेयर से फ़िल्टर किए गए ऑब्जेक्ट को लौटाएगा लेकिन जैसा कि मुझे एक फास्ट मैनर में प्रश्न का उत्तर देना है, इसलिए मैंने व्यापार तर्क परत में कोड समायोजित किया!


1
यह एक पूर्ण अनुकूलित दृष्टिकोण है जो मैं अपने अधिकांश रेस्ट एपीआई घटनाक्रमों के लिए उपयोग करता हूं क्योंकि मैं वास्तव में बाउंड्स के साथ काम का प्रशंसक नहीं हूं, हालांकि Django रेस्ट फ्रेमवर्क काफी लचीला है!
सैयद फैजान

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