我使用来自模型实例和Elasticsearch查询的数据为DetailView构建了精致的上下文。它可以很好地渲染模板,并遍历context ['payload']和context ['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.
答案 0 :(得分:0)
如果您只想返回JSON表示形式,则可以使用从PlaceDetailView继承但覆盖render_to_response
的类,以从上下文返回JSON响应,而不是渲染模板。
class PlaceFullView(PlaceDetailView):
def render_to_response(self, context, **response_kwargs):
return JsonResponse(context, **response_kwargs)