2012-02-13 10 views
54

Questo correlata a questa domanda: Django return json and html depending on client pythonvista Django JSON ritorno senza l'utilizzo di template

Ho un pitone api riga di comando per un app Django. Quando accedo all'app tramite l'api, dovrebbe restituire json e con un browser dovrebbe restituire html. Posso usare diversi URL per accedere alle diverse versioni, ma come faccio a rendere il template html e json nel views.py con un solo template?

Per rendere l'html userei:

return render_to_response('sample/sample.html....) 

Ma come avrei fatto lo stesso per JSON senza mettere un modello JSON? (Il tipo di contenuto dovrebbe essere application/json invece di text/html)

Edit 1:

Cosa avrebbe determinato le uscite JSON e html?

Così nel mio punto di vista:

if something: 
     return render_to_response('html_template',.....) 
else: 
     return HttpReponse(jsondata,mimetype='application/json') 

Grazie

+0

Non avete letto la mia risposta? – Marcin

+0

@Marcin Fondamentalmente gli hai detto "No, non farlo in questo modo" senza mostrargli un esempio del modo giusto. Questo è quello che sembra essere questo per ... – Izkata

+0

@Jimmy, se è quello che è successo, non avresti dovuto accettare la risposta di Marcin sull'altra domanda così in fretta. Aspetta almeno un giorno, qualcuno probabilmente avrebbe risposto con qualcosa come la risposta di Uku Loskit – Izkata

risposta

107

Penso che il problema si sia confuso riguardo a ciò che si desidera. Immagino che in realtà non stai provando a inserire l'HTML nella risposta JSON, ma piuttosto a restituire in alternativa HTML o JSON.

In primo luogo, è necessario comprendere la differenza principale tra i due. HTML è un formato di presentazione. Si occupa più di come visualizzare i dati che i dati stessi. JSON è il contrario. Sono dati puri - fondamentalmente una rappresentazione JavaScript di alcuni set di dati Python (in questo caso) che hai. Serve solo come un livello di interscambio, consentendo di spostare i dati da un'area della tua app (la vista) a un'altra area della tua app (il tuo JavaScript) che normalmente non hanno accesso l'una all'altra.

Con questo in mente, non "rendering" JSON, e non ci sono modelli coinvolti. Basta convertire tutti i dati in gioco (molto probabilmente quello che stai passando come contesto al modello) a JSON. Che può essere fatto tramite la libreria JSON di Django (simplejson), se si tratta di dati a mano libera, o il suo framework di serializzazione, se si tratta di un queryset.

simplejson

from django.utils import simplejson 

some_data_to_dump = { 
    'some_var_1': 'foo', 
    'some_var_2': 'bar', 
} 

data = simplejson.dumps(some_data_to_dump) 

serializzazione

from django.core import serializers 

foos = Foo.objects.all() 

data = serializers.serialize('json', foos) 

In entrambi i casi, è quindi passare i dati nella risposta:

return HttpResponse(data, content_type='application/json') 

[Edit] In Django 1.6 e EA il codice per la risposta di risposta è

return HttpResponse(data, mimetype='application/json') 
+0

Grazie per chiarimenti. Come faccio a determinare nelle mie opinioni che la richiesta di risposta è dall'api per il json? Vedi modifica sulla domanda. – Neeran

+1

Puoi usare 'request.is_ajax()'. Ma ciò richiede che l'intestazione 'HTTP_X_REQUESTED_WITH' sia impostata. La maggior parte delle librerie JavaScript lo fa automaticamente, ma se stai usando un altro tipo di client, dovrai assicurarti che lo imposti anche. In alternativa, puoi passare una querystring come '? Json' con l'URL e quindi controllare' request.GET.has_key ('json') ', che è probabilmente un po 'più infallibile. –

+14

Nota che simplejson è ora considerato [deprecato da Django 1.5] (https://docs.djangoproject.com/en/dev/releases/1.5/#system-version-of-simplejson-no-longer-used). Usa 'importazione json; json.dumps (data) 'invece. – Yonatan

7

Nel caso della risposta JSON non c'è il modello deve essere reso. I modelli servono a generare risposte HTML. Il JSON è la risposta HTTP.

Tuttavia, è possibile avere HTML che viene reso da un modello con la risposta JSON.

html = render_to_string("some.html", some_dictionary) 
serialized_data = simplejson.dumps({"html": html}) 
return HttpResponse(serialized_data, mimetype="application/json") 
+0

Devo prima serializzare gli oggetti? – Neeran

+0

simplejson.dumps() è ciò che fa la serializzazione. –

0

Se si vuole passare il risultato come un modello reso è necessario caricare e renderizzare un modello, passare il risultato di rendere agli json.This potrebbe apparire così:

from django.template import loader, RequestContext 

#render the template 
t=loader.get_template('sample/sample.html') 
context=RequestContext() 
html=t.render(context) 

#create the json 
result={'html_result':html) 
json = simplejson.dumps(result) 

return HttpResponse(json) 

In questo modo puoi passare un template reso come json al tuo cliente. Questo può essere utile se vuoi sostituire completamente ie. un contenente molti elementi diversi.

+1

Come nota a margine, 'render_to_string' è una scorciatoia per le linee da 3" renderizza il modello "ed è esistita da Django 1.0 – Izkata

+0

Un tale punto, potresti usare XML invece di JSON per lo scambio ... – jpaugh

2

È anche possibile controllare la richiesta accetta il tipo di contenuto come specificato nel rfc. In questo modo è possibile eseguire il rendering in base all'HTML e in cui il client accetta l'applicazione/jason è possibile restituire JSON nella risposta senza un modello richiesto

7

Sembra che il framework Django REST utilizzi l'intestazione HTTP accept in una Request per determinare automaticamente quale renderer da utilizzare:

http://www.django-rest-framework.org/api-guide/renderers/

Utilizzando l'HTTP accettare intestazione può fornire una fonte alternativa per il vostro "se qualcosa".

+0

Il collegamento è rotto. – Ajoy

+1

Grazie ... l'ho appena aggiornato. –

1
from django.utils import simplejson 
from django.core import serializers 

def pagina_json(request): 
    misdatos = misdatos.objects.all() 
    data = serializers.serialize('json', misdatos) 
    return HttpResponse(data, mimetype='application/json') 
4

Per il rendering i miei modelli in JSON in Django 1.9 ho dovuto fare quanto segue nel mio views.py:

from django.core import serializers 
from django.http import HttpResponse 
from .models import Mymodel 

def index(request): 
    objs = Mymodel.objects.all() 
    jsondata = serializers.serialize('json', objs) 
    return HttpResponse(jsondata, content_type='application/json')