J'ai cherché partout, mais je n'ai pas pu trouver un bon exemple.Django QuerySet avec ManyToMany étant passé au sérialiseur personnalisé
J'ai deux modèles, dont un a un ManyToManyField. J'essaie de passer un QuerySet qui a besoin d'informations à travers le ManyToManyField dans un sérialiseur personnalisé et renvoie une réponse JSON.
model.py
class Company(models.Model):
"""Company in database."""
founded = models.DateField(null=True)
name = models.CharField(max_length=60)
series = models.CharField(max_length=10, null=True)
valuation = models.DecimalField(max_digits=20, decimal_places=5, null=True)
description = models.TextField(null=True)
def __unicode__(self):
"""Return human-readable representation of company for debugging."""
return '<{}>'.format(self.name)
class Metric(models.Model):
"""Metrics for companies."""
name = models.CharField(max_length=30)
end_date = models.DateField()
start_date = models.DateField()
company = models.ManyToManyField(Company)
value = models.IntegerField()
def __unicode__(self):
"""Return human-readable representation of metric for debugging."""
return '<{}, {}>'.format(self.name, self.company)
views.py
class ClientAPI:
@classmethod
def _serialize(cls, objects):
def create_company_map():
return {c.id: c.name for c in Company.objects.all()}
# Replace company ids with company names
def map_company(obj, company_map):
if 'company' in obj:
obj['company'] = company_map[obj['company']]
return obj
company_map = create_company_map()
raw = serializers.serialize('python', objects)
res = [dict(map_company(obj['fields'], company_map)) for obj in raw]
return res
@classmethod
def get_metrics(cls, request):
all_metrics = Metric.objects.all().order_by('end_date')
serialized_metrics = ClientAPI._serialize(all_metrics)
return JsonResponse(serialized_metrics, safe=False, json_dumps_params=None)
@classmethod
def get_metrics_by_company(cls, request, company_name):
metrics_by_company = Metric.objects.filter(company__name=company_name).order_by('end_date')
serialized_metrics_by_company = ClientAPI._serialize(metrics_by_company)
return JsonResponse(serialized_metrics_by_company, safe=False, json_dumps_params=None)
Je ne peux pas changer le sérialiseur, parce que j'ai d'autres méthodes qui en dépendent. Lorsque j'exécute ce code, j'obtiens:
TypeError: unhashable type: 'list'
Tout renseignement sur la façon de résoudre ce problème est grandement apprécié! Juste au cas, c'est le retraçage.
Traceback (most recent call last):
File "/Users/jackiehuynh/anaconda/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/jackiehuynh/anaconda/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/jackiehuynh/Lytmus/question_1/client/views.py", line 167, in get_metrics
serialized_metrics = ClientAPI._serialize(all_metrics)
File "/Users/jackiehuynh/Lytmus/question_1/client/views.py", line 65, in _serialize
res = [dict(map_company(obj['fields'], company_map)) for obj in raw]
File "/Users/jackiehuynh/Lytmus/question_1/client/views.py", line 60, in map_company
obj['company'] = company_map[obj['company']]
TypeError: unhashable type: 'list'
J'ai bien compris cette partie, mais je suis un peu perplexe sur la façon de le résoudre. Des idées? La seule chose que je ne peux pas changer est le sérialiseur, mais tout le reste dans views.py et model.py sont modifiables. – sabellachan
Veuillez jeter un oeil à la réponse mise à jour. – AKS