Dzięki @astevanovic wskazuje właściwy kierunek.
Zauważyłem, że przesłonięcie metody dehydrate
przetwarzania tylko niektórych określonych pól jest nieco mniej żmudne niż przesłonięcie metody full_hydrate
, aby pominąć pola.
W pogoni za możliwością ponownego użycia, wymyśliłem następujące fragmenty kodu. Nadzieję, że dobrze byłoby dla niektórych:
class BeeModelResource(ModelResource):
def dehydrate(self, bundle):
bundle = super(BeeModelResource, self).dehydrate(bundle)
bundle = self.dehydrate_partial(bundle)
return bundle
def dehydrate_partial(self, bundle):
for field_name, resource_field in self.fields.items():
if not isinstance(resource_field, RelatedField):
continue
if resource_field.full: # already dehydrated
continue
if not field_name in self._meta.partial_fields:
continue
if isinstance(resource_field, ToOneField):
fk_object = getattr(bundle.obj, resource_field.attribute)
fk_bundle = Bundle(obj=fk_object, request=bundle.request)
fk_resource = resource_field.get_related_resource(fk_object)
bundle.data[field_name] = fk_resource.dehydrate_selected(
fk_bundle, self._meta.partial_fields[field_name]).data
elif isinstance(resource_field, ToManyField):
data = []
fk_objects = getattr(bundle.obj, resource_field.attribute)
for fk_object in fk_objects.all():
fk_bundle = Bundle(obj=fk_object, request=bundle.request)
fk_resource = resource_field.get_related_resource(fk_object)
fk_bundle = fk_resource.dehydrate_selected_fields(
fk_bundle, self._meta.partial_fields[field_name])
data.append(fk_bundle.data)
bundle.data[field_name] = data
return bundle
def dehydrate_selected_fields(self, bundle, selected_field_names):
# Dehydrate each field.
for field_name, field_object in self.fields.items():
# A touch leaky but it makes URI resolution work.
# (borrowed from tastypie.resources.full_dehydrate)
if field_name in selected_field_names and not self.is_special_fields(field_name):
if getattr(field_object, 'dehydrated_type', None) == 'related':
field_object.api_name = self._meta.api_name
field_object.resource_name = self._meta.resource_name
bundle.data[field_name] = field_object.dehydrate(bundle)
bundle.data['resource_uri'] = self.get_resource_uri(bundle.obj)
bundle.data['id'] = bundle.obj.pk
return bundle
@staticmethod
def is_special_fields(field_name):
return field_name in ['resource_uri']
Z przykład @sigmus', zasoby będą potrzebne 3 zmiany:
- zarówno zasobów użyje
BeeModuleResource
jako super klasy (lub dodać do jednej dehydrate_partial
zasobów i dehydrate_selected
do drugiego.)
- rozbrojony
full=True
na jednej z zasobu
- dodać
partial_fields
do zasobu Meta
zasobu rozbrojony
`` `
class ClientResource(BeeModelResource): # make BeeModelResource a super class
projects = fields.ToManyField(
'api.resources.ProjectResource', 'project_set'
) # remove full=True
class Meta:
queryset = Client.objects.all()
resource_name = 'client'
partial_fields = {'projects': ['memo', 'title']} # add partial_fields
class ProjectResource(BeeModelResource): # make BeeModelResource a super class
client = fields.ForeignKey(ClientResource, 'client', full=True)
class Meta:
queryset = Project.objects.all()
resource_name = 'project'
Dzięki za cynk dwóch zasobów, to pomogło mi się dużo ... :) –
@MarkShust: Jestem stoi podobny rodzaj problemu, można proszę opracować bardziej na którykolwiek z metoda, która działała dla ciebie? –
@NikhilAgrawal jeśli dobrze pamiętam, zrobiłem dwa zasoby, jeden z full = True, jeden z full = False, sufiks full = False with Simple, więc wiem, który zasób jest czym. następnie odwołaj się do odpowiedniego zasobu. –