Я создаю сложный контекст для DetailView с данными из экземпляра модели и запроса Elasticsearch.Он хорошо обрабатывает шаблон, просматривая данные в списках context ['payload'] и context ['traces'].Если я отображаю {{payload}} и {{traces}}, я могу видеть все данные в виде необработанного JSON.
Я хотел бы предоставить на странице кнопку для загрузки этого JSON в виде файла.
Вот рабочий код DetailView 'PlacePortalView ()', за которым последовала моя попытка изменить его как функцию, placeFull (), а затем трассировка стека ошибки, которую я получил.
PlacePortalView () - прекрасно отображает шаблон
class PlacePortalView(DetailView):
template_name = 'places/place_portal.html'
def get_object(self):
id_ = self.kwargs.get("id")
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
q = {"query":{"bool": {"must": [{"match":{"_id": id_}}]}}}
pid=es.search(index='whg', doc_type='place', body=q)['hits']['hits'][0]['_source']['place_id']
self.kwargs['pid'] = pid
return get_object_or_404(Place, id=pid)
def get_success_url(self):
id_ = self.kwargs.get("id")
return '/places/'+str(id_)+'/detail'
def minmax(timespans):
starts = sorted([t['start']['in'] for t in timespans])
ends = sorted([t['end']['in'] for t in timespans])
minmax = [min(starts), max(ends)]
def get_context_data(self, *args, **kwargs):
context = super(PlacePortalView, self).get_context_data(*args, **kwargs)
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
id_ = self.kwargs.get("id")
pid = self.kwargs.get("pid")
place = get_object_or_404(Place, id=pid)
context['whg_id'] = id_
context['payload'] = [] # parent and children if any
context['traces'] = [] #
ids = [pid]
# get child record ids from index
q = {"query": {"parent_id": {"type": "child","id":id_}}}
children = es.search(index='whg', doc_type='place', body=q)['hits']
for hit in children['hits']:
ids.append(int(hit['_id']))
# database records for parent + children into 'payload'
qs=Place.objects.filter(id__in=ids).order_by('-whens__minmax')
for place in qs:
ds = get_object_or_404(Dataset,id=place.dataset.id)
record = {
"whg_id":id_,
"dataset":{"id":ds.id,"label":ds.label},
"place_id":place.id,
"src_id":place.src_id,
"purl":ds.uri_base+str(place.id) if 'whgaz' in ds.uri_base else ds.uri_base+place.src_id,
"title":place.title,
"ccodes":place.ccodes,
"names":[name.jsonb for name in place.names.all()],
"types":[t.jsonb for t in place.types.all()],
"links":[link.jsonb for link in place.links.all()],
"geoms":[geom.jsonb for geom in place.geoms.all()],
"whens":[when.jsonb for when in place.whens.all()],
"related":[rel.jsonb for rel in place.related.all()],
"descriptions":[descr.jsonb for descr in place.descriptions.all()],
"depictions":[depict.jsonb for depict in place.depictions.all()]
}
context['payload'].append(record)
# get traces
qt = {"query": {"bool": {"must": [{"match":{"body.whg_id": id_ }}]}}}
trace_hits = es.search(index='traces', doc_type='trace', body=qt)['hits']['hits']
for h in trace_hits:
context['traces'].append({
'trace_id':h['_id'],
'target':h['_source']['target'],
'body':next((x for x in h['_source']['body'] if x['whg_id'] == id_), None),
'bodycount':len(h['_source']['body'])
})
return context
placeFull (), пытаясь получить загруженный файл JSON
, вызываемый
path('<int:id>/full', views.placeFull, name='place-full')
def placeFull(request,id):
response = HttpResponse(content_type='text/json')
response['Content-Disposition'] = 'attachment;filename="place-full.json"'
#template_name = 'places/place_portal.html'
def get_object(self):
id_ = self.kwargs.get("id")
print('args',self.args,'kwargs:',self.kwargs)
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
q = {"query":{"bool": {"must": [{"match":{"_id": id_}}]}}}
pid=es.search(index='whg', doc_type='place', body=q)['hits']['hits'][0]['_source']['place_id']
self.kwargs['pid'] = pid
return get_object_or_404(Place, id=pid)
#def get_success_url(self):
#id_ = self.kwargs.get("id")
#return '/places/'+str(id_)+'/detail'
def minmax(timespans):
starts = sorted([t['start']['in'] for t in timespans])
ends = sorted([t['end']['in'] for t in timespans])
#minmax = {'start':min(starts), 'end':max(ends)}
minmax = [min(starts), max(ends)]
def get_context_data(self, *args, **kwargs):
context = super(placeFull, self).get_context_data(*args, **kwargs)
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
id_ = self.kwargs.get("id")
pid = self.kwargs.get("pid")
place = get_object_or_404(Place, id=pid)
context['whg_id'] = id_
context['payload'] = [] # parent and children if any
context['traces'] = [] #
ids = [pid]
# get child record ids from index
q = {"query": {"parent_id": {"type": "child","id":id_}}}
children = es.search(index='whg', doc_type='place', body=q)['hits']
for hit in children['hits']:
ids.append(int(hit['_id']))
# database records for parent + children into 'payload'
qs=Place.objects.filter(id__in=ids).order_by('-whens__minmax')
for place in qs:
ds = get_object_or_404(Dataset,id=place.dataset.id)
record = {
"whg_id":id_,
"dataset":{"id":ds.id,"label":ds.label},
"place_id":place.id,
"src_id":place.src_id,
"purl":ds.uri_base+str(place.id) if 'whgaz' in ds.uri_base else ds.uri_base+place.src_id,
"title":place.title
}
context['payload'].append(record)
# get traces
qt = {"query": {"bool": {"must": [{"match":{"body.whg_id": id_ }}]}}}
trace_hits = es.search(index='traces', doc_type='trace', body=qt)['hits']['hits']
for h in trace_hits:
context['traces'].append({
'trace_id':h['_id'],
'target':h['_source']['target'],
'body':next((x for x in h['_source']['body'] if x['whg_id'] == id_), None),
'bodycount':len(h['_source']['body'])
})
response.write(context['payload'])
response.write(context['traces'])
return response
трассировка стека
Environment:
Request Method: GET
Request URL: http://localhost:8000/places/12392121/full
Django Version: 2.1.7
Python Version: 3.6.3
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
'bootstrap_modal_forms',
'django_celery_beat',
'django_celery_results',
'django_extensions',
'djgeojson',
'fontawesome',
'leaflet',
'mathfilters',
'rest_framework',
'rest_framework_datatables',
'accounts.apps.AccountsConfig',
'areas.apps.AreasConfig',
'datasets.apps.DatasetsConfig',
'main.apps.MainConfig',
'maps.apps.MapsConfig',
'places.apps.PlacesConfig',
'search.apps.SearchConfig',
'traces.apps.TracesConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/Users/karlg/envs/whg/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/Users/karlg/envs/whg/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
137. "returned None instead." % (callback.__module__, view_name)
Exception Type: ValueError at /places/12392121/full
Exception Value: The view places.views.placeFull didn't return an HttpResponse object. It returned None instead.