Merci @astevanovic de pointer dans la bonne direction.
J'ai trouvé que le remplacement de la méthode dehydrate
pour traiter uniquement certains champs spécifiés est un peu moins fastidieux que de surcharger la méthode full_hydrate
pour ignorer les champs.
Dans la poursuite de la réutilisation, je suis venu avec les extraits de code suivants. Espérons que ce serait utile à certains:
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']
Avec l'exemple de @sigmus, les ressources auront besoin 3 modifications:
- deux ressources utilisera
BeeModuleResource
comme super-classe (ou, ajouter dehydrate_partial
à un ressources et dehydrate_selected
à l'autre.)
- unset
full=True
sur l'une des ressources
- ajouter
partial_fields
dans la ressource Meta
la ressource unset
`` `
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'
Merci pour la pointe des deux ressources, cela me ont beaucoup aidé ... :) –
@MarkShust: Je suis confronté le même genre de problème, pouvez-vous s'il vous plaît donner des précisions sur l'un des la méthode qui a fonctionné pour vous? –
@NikhilAgrawal Si je me souviens bien, je viens de faire deux ressources, une avec full = True, une avec full = False, suffixé le full = False avec Simple, donc je sais quelle ressource est quoi. puis référencez la ressource appropriée. –