6

मेरे पास एक एंगुलरजेएस प्रोजेक्ट है जो Django Rest Framework (DRF) के माध्यम से Django को ढांचे के रूप में उपयोग करता है।Django Rest Framework खुद से संबंधित कई फ़ील्ड में से कई

मैंने एक समूह मॉडल बनाया है और इसके लिए एक सीरिएलाइज़र क्लास स्थापित किया है, हालांकि मैं अब उस मॉडल पर एक नया क्षेत्र स्थापित करना चाहता हूं जिसे related_groups कहा जाता है, जो प्राथमिक कुंजी की सरणी के रूप में उसी मॉडल (समूह) को संदर्भित करेगा ।

मुझे नहीं पता कि धारावाहिक में आत्म-संदर्भ करना संभव है या नहीं, और मुझे नहीं पता कि आगे के अंत से संबंधित समूहों से कैसे गुजरना है, जिसे उपयोगकर्ताओं द्वारा चुना और चुना जा सकता है समूह के मालिक कौन है। मैं उस क्षेत्र को अन्य समूह पंक्तियों की प्राथमिक कुंजी का संदर्भ देना चाहता हूं, और संबंधित समूह संबंध स्थापित करने के लिए समूह के उस संग्रह के माध्यम से पुनरावृत्त करना चाहता हूं।

class GroupSerializer(serializers.ModelSerializer): 

class Meta: 
    model = mod.Group 
    fields = (
     'group_id', 
     'group_name', 
     'category', 
     'related_groups', 
    ) 

और प्रतिनिधित्व बिल्कुल प्रतीत होता है जो मैं चाहता:

GroupSerializer(): 
    group_id = IntegerField(read_only=True) 
    group_name = CharField(max_length=100) 
    category = CharField(max_length=256, required=False 
    related_groups = PrimaryKeyRelatedField(many=True, queryset=Group.objects.all(), required=False) 

और मॉडल के रूप में प्रस्तुत किया जाता है:

class Group(models.Model): 
    """ 
    Model definition of a Group. Groups are a collection of users (i.e. 
    Contacts) that share access to a collection of objects (e.g. Shipments). 
    """ 
    group_id = models.AutoField(primary_key=True) 
    group_name = models.CharField(max_length=100) 
    owner_id = models.ForeignKey('Owner', related_name='groups') 
    category = models.CharField(max_length=256) 
    related_groups = models.ManyToManyField('self', blank=True, null=True) 
    history = HistoricalRecords() 

    def __unicode__(self): 
     return u'%s' % (self.group_name) 

    def __str__(self): 
     return '%s' % (self.group_name) 

दृश्य इस मॉडल तक पहुँचने बहुत सरल CRUD दृश्य है :

@api_view(['GET', 'PUT', 'DELETE']) 
@authentication_classes((SessionAuthentication, BasicAuthentication)) 
@permission_classes((IsAuthenticated, HasGroupAccess)) 
def group_detail(request, pk, format=None): 
    group, error = utils.get_by_pk(pk, mod.Group, request.user) 
    if error is not None: 
     return error 
    if request.method == 'GET': 
     serializer = ser.GroupSerializer(group) 
     return Response(serializer.data) 
    elif request.method == 'PUT': 
     return utils.update_object_by_pk(request, pk, mod.Group, 
             ser.GroupSerializer) 
    elif request.method == 'DELETE': 
     return utils.delete_object_by_pk(request.user, pk, mod.Group) 

कौन सा कुछ sanitizing और सत्यापन के तरीकों कॉल:

def update_object_by_pk(request, pk, obj_type, serializer): 
    try: 
     with transaction.atomic(): 
      obj, error = select_for_update_by_pk(pk, obj_type, request.user) 
      if error is not None: 
       return error 
      obj_serializer = serializer(obj, data=request.data) 

      if obj_serializer.is_valid(): 
       obj_serializer.save() 
      else: 
       response = ("Attempt to serialize {} with id {} failed " 
          "with errors {}").format(str(obj_type), str(pk), 
                str(serializer.errors)) 
       return Response(response, status=status.HTTP_400_BAD_REQUEST) 
    except Exception as e: 
     response = ("Error attempting to update {} with ID={}. user={}, " 
        "error={}".format(str(obj_type), str(pk), 
             str(request.user.email), str(e))) 
     return Response(response, status=status.HTTP_400_BAD_REQUEST) 
    else: 
     resp_str = ("Successfully updated {} with ID={}".format(str(obj_type), 
                   str(pk))) 
     return Response(resp_str, status=status.HTTP_200_OK) 

जो कहता है:

def select_for_update_by_pk(pk, mod_type, user): 
    response = None 
    obj = None 
    try: 
     obj = mod_type.objects.select_for_update().get(pk=pk) 
    except mod_type.DoesNotExist: 
     resp_str = ("{} could not be found with ID={}.". 
        format(str(mod_type), str(pk))) 
     response = Response(resp_str, status=status.HTTP_404_NOT_FOUND) 
    return obj, response 

जो सिर्फ एक आवरण के आसपास select_for_update() Django तरीका है।

माइग्रेशन ने समूह_संबंधित_ग्रुप नामक एक नई तालिका बनाई, जिसे आईडी, एक_ग्रुप और एक टू_ग्रुप कॉलम के साथ बनाया गया था, जो Django द्वारा उन संबंधों को स्थापित करने के लिए जंक्शन/लुकअप के रूप में उपयोग किया जाता था।

मैं उस अंतराल पर व्यक्तिगत रूप से लिख सकता हूं, लेकिन धारावाहिक समूह Serializer डिफ़ॉल्ट रूप से एकाधिक मानों को अनुमति देना नहीं चाहता है।

तो, पीके अनुरोध 1 का उपयोग करके 'पी' के मूल्य को पीके 1 के साथ समूह में सफल करने के लिए एक पुष्ट अनुरोध का उपयोग करना सफल है। हालांकि, एक उपयोगिता विधि के दृश्य के माध्यम से इसे वापस ट्रेसिंग ['2','3'], [2,3], 2,3 और '2','3'

डाल करने के लिए प्रयास करता है, मुझे लगता है कि यह serializer.is_valid() अनुरोध असफल रहने के है, इसलिए कि बनाता है मुझे लगता है कि यह एक many=True मुद्दा है, लेकिन मैं डॉन ' टी इस विशेष आत्म-संदर्भित ManyToManyField समस्या के लिए उपयोग करने के लिए कौन सा रिलेशनशिप serializer का पता नहीं है।

जब डिबगिंग, मैं इस तरह तंत्र लॉग को serializer.is_valid() त्रुटियों outputting हूँ:

 response = ("Attempt to serialize {} with id {} failed " 
        "with errors {}").format(str(obj_type), str(pk), 
              str(serializer.errors)) 
     logger.exception(response) 

और मैं प्रतिक्रिया के रूप में यह अपवाद संदेश प्राप्त हो रहा:

Message: "Attempt to serialize <class 'bioapi.models.Group'> with id 1 failed with errors"

obj_serializer के लिए डीबग त्रुटि आउटपुट।त्रुटि

obj_serializer.error of {'related_groups': ['Incorrect type. Expected pk value, received str.']}

यहाँ है और request.data पर डिबग संदेश के है:

{'group_name': 'Default Guest Group', 'related_groups': [1], 'group_id': 2, 'category': 'guest'}

जो सफल होता है, और

<QueryDict: {'group_name': ['requestomatic'], 'related_groups':['2,2'], category': ['guest']}>

जो विफल रहता है। अब यह देखकर, मैं सोच रहा हूं कि पोस्टमैन फॉर्म-डेटा स्वरूपण समस्या है या नहीं। अगर ऐसा है तो मैं बहुत बेवकूफ महसूस करने जा रहा हूं।

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

क्या मेरे मॉडल में ManyToManyField का उपयोग करना संभव है जो Django Rest Framework (DRF) और इसके धारावाहिकों का उपयोग करके आत्म-संदर्भित है? यदि हां, तो कैसे?

+0

कृपया बताएं कि आपको वह 'GroupSerializer से क्या मतलब है() : 'आपके दूसरे स्निपेट में – e4c5

+1

एक बार 'serializer.is_valid()' विफल हो गया, 'serializer.errors' की सामग्री क्या है? यह आमतौर पर अच्छे संकेत देता है कि यह क्यों विफल रहा है। –

+0

@ ई 4 सी 5, धारावाहिक संबंध दस्तावेज में वर्णित विधि के साथ धारावाहिक संबंध का निरीक्षण, यहां: http://www.django-rest-framework.org/api-guide/relations/#inspecting-relationships, और रिश्ते में प्रतीत होता है क्रम में हो। – Smittles

उत्तर

3

नेस्टेड क्रमबद्धता के मामले की तरह दिखता है। मॉडल होना चाहिए -

class Group(models.Model): 
    group_id = models.IntegerField(read_only=True) 
    group_name = models.CharField(max_length=100) 
    category = models.CharField(max_length=256, required=False) 
    related_groups = models.ForeignKey('self', required=False, related_name='children') 

और serializers -

class GroupSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Group 
     fields = (
      'group_id', 'group_name', 'category', 'related_groups', 
     ) 

class NestedGroupSerializer(serializers.ModelSerializer): 
    children = GroupSerializer(many=True, read_only=True) 

    class Meta: 
     model = Group 
     fields = ('group_id', 'group_name', 'category', 'related_groups', 'children') 

फिर आप सभी संबंधित समूह तक पहुँचने के लिए NestedGroupSerializer उपयोग कर सकते हैं।

डिफ़ॉल्ट रूप से नेस्टेड धारावाहिक केवल पढ़ने के लिए हैं। यदि आप नेस्टेड सीरियलाइज़र फ़ील्ड में लेखन-संचालन का समर्थन करना चाहते हैं तो आपको स्पष्ट रूप से निर्दिष्ट करने के लिए कि कैसे बच्चे संबंधों को सहेजा जाना चाहिए, बनाने के लिए बनाने() और/या अद्यतन() विधियों को बनाना होगा।

उम्मीद है कि मदद करता है।

+0

यह पद्धति वैधता पर विफल रही है, जैसा मेरा है। serializer.is_valid() '[2,3]' या '2,3' गुजरते समय झूठी के रूप में वापस आता है। हालांकि, अनुभव एक ही पूर्णांक को '2' या '3' से गुजरने के समान होता है – Smittles

+0

मेरे पास पहले से ही संबंधित_ग्रुप के लिए एक फ़ील्ड है - और ManyToManyField के लिए बनाई गई एक तालिका - तो मुझे' बच्चों 'की आवश्यकता क्यों है? अगर मुझे एक ही मॉडल से संबंधित कईToManyField मिल गया है तो मुझे एक संबंधित_नाम की आवश्यकता क्यों है? – Smittles

+0

इसके अलावा, मुझे एक से अधिक संबंधित समूह की आवश्यकता है, इसलिए ManyToManyField उपयोग। ManyToManyField का उपयोग डेटाबेस में एक रिलेशनशिप टेबल बनाता है - त्वरित संबंधों के लिए एकदम सही है जहां एक नाइटक्लब समूह में कई डीजे समूह हो सकते हैं, जहां नाइटक्लब के सदस्यों का एक सेट है और डीजे 1 का एक और सेट है, और डीजे 2 में अभी तक एक और सेट है। – Smittles

1

दृश्य के रूप में ModelViewSet उपयोग करके देखें:

class GroupViewSet(viewsets.ModelViewSet): 
    queryset = models.Group.objects.all() 
    serializer_class = serializers.GroupSerializer 
    authentication_classes = (SessionAuthentication, BasicAuthentication) 
    permission_classes = (IsAuthenticated, HasGroupAccess) 

और अपनी urls.conf, की तरह कुछ: rest_framework आयात रूटर से आयात विचारों से

router = routers.SimpleRouter() 
router.register(r'group', views.GroupViewset) 
urlpatterns = router.urls