2013-03-08 3 views

답변

2

이것은 내가 그것을 해결하는 방법입니다

class MenuResource(ModelResource): 
    parent = fields.ForeignKey('self', 'parent', null=True) 

    class Meta: 
     serializer = PrettyJSONSerializer() 
     queryset = Menu.objects.all().select_related('parent') 
     include_resource_uri = False 
     fields = ['name'] 

    def get_child_data(self, obj): 
     data = { 
      'id': obj.id, 
      'name': obj.name, 
     } 
     if not obj.is_leaf_node(): 
      data['children'] = [self.get_child_data(child) \ 
           for child in obj.get_children()] 
     return data 

    def get_list(self, request, **kwargs): 

     base_bundle = self.build_bundle(request=request) 
     objects = self.obj_get_list(bundle=base_bundle, 
            **self.remove_api_resource_names(kwargs)) 
     sorted_objects = self.apply_sorting(objects, options=request.GET) 

     paginator = self._meta.paginator_class(
      request.GET, sorted_objects, 
      resource_uri=self.get_resource_uri(), limit=self._meta.limit, 
      max_limit=self._meta.max_limit, 
      collection_name=self._meta.collection_name 
     ) 
     to_be_serialized = paginator.page() 

     from mptt.templatetags.mptt_tags import cache_tree_children 
     objects = cache_tree_children(objects) 

     bundles = [] 

     for obj in objects: 
      data = self.get_child_data(obj) 
      bundle = self.build_bundle(data=data, obj=obj, request=request) 
      bundles.append(self.full_dehydrate(bundle)) 

     to_be_serialized[self._meta.collection_name] = bundles 
     to_be_serialized = self.alter_list_data_to_serialize(request, 
                  to_be_serialized) 
     return self.create_response(request, to_be_serialized) 

당신은 페이지 매김을 사용하지 않는 경우 당신은 단지 그 부분을 걸릴 수 있습니다. 그게 내가 한 짓이야. 당신은 아마 당신의 아이들이 단순히 children 시설에 full=True 포인팅으로 ToManyField을 접선으로 직렬화 수 있었던 cache_tree_children 방법없이

6

는 :

class MenuResource(ModelResource): 

    children = fields.ToManyField('self', 'children', null=True, full=True) 
    parent = fields.ToOneField('self', 'parent', null=True) 

    class Meta: 
     queryset = Menu.objects.all() 

우선 자신의 ToManyField 서브 클래스를 쓸 수있는 cache_tree_children 기능을 구현하려면 표준 dehydrate 기능. 난 단지 아주 피상적으로이 솔루션을 테스트 한 것으로, 참고 :

이 방법의 주요 장점 중
def dehydrate(self, bundle): 
    if not bundle.obj or not bundle.obj.pk: 
    if not self.null: 
     raise ApiFieldError("The model '%r' does not have a primary key and can not be used in a ToMany context." % bundle.obj) 

     return [] 

    the_m2ms = None 
    previous_obj = bundle.obj 
    attr = self.attribute 

    if isinstance(self.attribute, basestring): 
     attrs = self.attribute.split('__') 
     the_m2ms = bundle.obj 

     for attr in attrs: 
      previous_obj = the_m2ms 
      try: 
       the_m2ms = getattr(the_m2ms, attr, None) 
      except ObjectDoesNotExist: 
       the_m2ms = None 

      if not the_m2ms: 
       break 

    elif callable(self.attribute): 
     the_m2ms = self.attribute(bundle) 

    if not the_m2ms: 
     if not self.null: 
      raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) 

     return [] 

    self.m2m_resources = [] 
    m2m_dehydrated = [] 

    # There goes your ``cache_tree_children`` 
    for m2m in cache_tree_children(the_m2ms.all()): 
     m2m_resource = self.get_related_resource(m2m) 
     m2m_bundle = Bundle(obj=m2m, request=bundle.request) 
     self.m2m_resources.append(m2m_resource) 
     m2m_dehydrated.append(self.dehydrate_related(m2m_bundle, m2m_resource)) 

    return m2m_dehydrated 

하나는 당신이 더 이상 세부/목록보기 제약/차이 걱정 할 필요가 없습니다 없다는 것입니다. 자신의 필요에 맞는 일종의 기본 동작이 생길 때까지 리소스의이 부분을 더 자세히 매개 변수화 할 수도 있습니다. 필드 기반, 즉. 나는 그것이 멋지다라고 생각한다.