2009-09-29 9 views
5

El otro día escribí algunos AJAX para una aplicación de Django en la que he estado trabajando.una mejor manera de hacer ajax en django

Vengo de Ruby on Rails, así que no he hecho mucho en el camino de raw JS.

Así que basado en Rails parciales, que algo similar a lo siguiente en una especie de pseudocódigo, no sudan los detalles:

1) la función JS usando Ajax.Updater del prototipo ('tablediv' es el ID de la mesa que quería actualizar Ajaxily, y señalando url para la visión apropiada Django)

function updateTable(){ 
     new Ajax.Updater('tablediv',url {params: params....etc 

2) vista de Django que tiene nuevos datos para rellenar la tabla con:

def ajaxTable 
    objects = Objects.object.all... 
    return render_to_response('ajaxtable.html',objects) 

3) ajaxtable.html era sólo una especie de rieles "parcial", así que básicamente una mesa w/o <table></table> ...:

<th>{{object.data}}</th> 
    <td>{{object.moredata}}</td> 

por lo que mi pregunta real:

Esto parecía hacky para mí , De alguna manera lo lancé después de cansarme de buscar en línea lo que quería.

¿Es así como se hace? Funciona bien, simplemente no sé lo suficiente como para saberlo, ¿sabes?

Respuesta

1

¿Qué parece exactamente hacky al respecto? Parece una forma perfectamente válida de hacer algo.

Supongo que una alternativa sería serialising a json y enviándola a un javascript templating snippet.

+0

Eso es lo que jugué, pero en ese momento no sabía tanto javascript como sé, así que simplemente envíe los objetos como JSON, cree los literales de los objetos javascript y luego tablediv.innerHTML = foo ? – Joel

+0

JSON * * es un objeto literal por lo que el bueno de usarlo en javascript es que usted no tiene que hacer nada con ella que realmente se utilicen una vez que lo tienes. Me gusta usar JSON en conjunción con el sistema de plantillas que he vinculado anteriormente (jQuery, no prototipo, lo siento) ya que sólo puede pasar el JSON devuelto directamente a la plantilla que la configuración y va a trabajar. – Steerpike

2

No importa qué, vas a necesitar por lo menos dos cosas:

  1. el código JavaScript para realizar la llamada (que tiene este) código del lado del

  2. servidor para manejar la solicitud (esta es su vista y url-config)

No hay absolutamente nada de "hacky" sobre esto.

Lo tercero, su archivo de plantilla, es opcional, pero en general es una buena práctica. Desea separar su marcado del código, por muchas razones.

Así que creo que tiene la idea correcta. Continua.

+0

agradable, gracias por la respuesta, he terminado el proyecto y siguió adelante, pero algo me ha pinchado desde entonces (cuando estoy en medio de algo que no puedo dejar de preguntar en un foro o apilar overflow..I Don 't tienen la paciencia :), bueno saber que mis instintos no son completamente ridiculus – Joel

5

Depende de lo que quieras hacer, creo. Ajax es una gama bastante amplia de escenarios desde Google Maps hasta un simple autocompletado que varía mucho en complejidad y en el mejor enfoque.

Sin embargo, hay algunas cosas útiles que puede hacer esa ayuda.

1) Nivel de plantilla

Asegúrate de que tienes "django.core.context_processors.request" en su entorno TEMPLATE_CONTEXT_PROCESSORS.Entonces puedes hacer esto;

{% if not request.is_ajax %} 
<html> 
    <head> 
    ... 
    </head> 
    <body> 
    ... 
{% endif %} 
actual content 
{% if not request.is_ajax %} 
</body> 
</html> 
{% endif %} 

Básicamente luego dicen que esta página es/test/Usted puede hacer una petición del navegador y obtener el contenido completo o una solicitud a través de JavaScript y acaba de obtener el contenido. Hay un blog en algún lugar que explica esto con más detalle, pero no puedo encontrarlo en este momento.

2) En la vista

En la plantilla que se acaba de acceder al objeto pedido en la plantilla. En la vista, puedes hacer cosas muy similares.

def my_view(request): 
    if requst.is_ajax(): 
     # handle for Ajax requests 

    # otherwise handle 'normal' requests 
    return HttpResponse('Hello world') 

Los métodos anteriores no les gusta hacer de manera diferente de lo que haces, pero le permiten reutilizar los puntos de vista y lo escribe el bit más concisa. Realmente no diría que lo que estás haciendo es incorrecto o hacky, pero podrías escribirlo para hacerlo más conciso y reutilizar las plantillas y vistas.

decir, por ejemplo, podría tener solo una plantilla y si es una solicitud de Ajax solo debe devolver la sección que deberá actualizarse. En tu caso, serían las vistas de las tablas.

+0

eso parece muy inteligente, que viene de usar rubí incrustado que atrae a mí ... tal vez demasiado inteligente ... jaja no – Joel

+0

hTML en los comentarios ... – Joel

+0

demasiado inteligente? Realmente me gusta bastante Puede grandes trozos totalmente Ajaxify de un sitio web de forma rápida, por desgracia, no hay manera de tener más de un 'bloque ajax' por plantilla ... hmm Me pregunto cómo se puede hacer eso. –

4

Estoy bastante tarde, pero quiero documentar cómo combinar y adaptar las soluciones presentadas por d0ugal de una manera que resuelva un código de plantilla mucho más limpio.

Tengo un modelo que representa personas de contacto.

El (genérico) a fin de obtener una Persona de contacto es el siguiente:

def contcactperson_detail_view(request, name): 
    try: 
     person = ContactPerson.objects.get(slug=name) 
    except: 
     raise Http404 
    if request.is_ajax(): 
     return contcactperson_detail_view_ajax(request, person) 
    return list_detail.object_detail(
      request, 
      queryset = ContactPerson.objects.all(), 
      object_id = person.id, 
      template_object_name = "contactperson", 
     ) 

@render_to('cms/contactperson_detail_ajax.html')  
def contcactperson_detail_view_ajax(request, person): 
    return {'contactperson':person, 'is_ajax':True} 

La plantilla para renderizar la vista que se encarga de una Persona de contacto se llama contcactperson_detail_view.html:

{% extends "index.html" %} 
{% block textpane %} 

<h1 id="mainheader">{{ contactperson.first_name }} {{ contactperson.family_name }} </h1> 
<div class="indentation">&nbsp;</div> 
{% include 'cms/contactperson_detail_photo.html' %}                           
<div id="text_pane"> 

{% include 'cms/contactperson_detail_textpane.html' %} 
</div> 
{% endblock %} 

Incluye dos sub- plantillas

contactperson_detail_textpane.html 


<p>{{ contactperson.description }}</p> 
<ul> 
    <li> 
     <dl> 
      <dt>Email</dt> 
      <dd> 
       {{ contactperson.mail }} 
      </dd> 
     </dl> 
    </li> 
    <li> 
     <dl> 
      <dt>Contact Person for</dt> 
      <dd> 
       <ul> 
       {% for c in contactperson.categories.all %} 
        <li><a href="{% url category-view c.slug %}">{{ c }}</a></li> 
       {% endfor %} 
       </ul> 
      </dd> 
     </dl> 
    </li> 
</ul> 

y contactperson_detail_photo.html

{% with contactperson.photo.detailphoto as pic %} 
    {% with pic.url as pic_url %}  
    <div {% if not is_ajax %}id='imageContainer'{% endif %} style="float: right;padding-right:0.5em; 
            padding-bottom: 1em; padding-left:0.5em;clear:both; 
            width:{{ pic.width }}px"> 
     <div style="width:{{ pic.width}}px">      
       <img style="clear:both" src="{{ pic_url }}" alt="{{ i.name }}"/> 
     </div>                              
    </div> 
    {% endwith %} 
{% endwith %} 

se usarán estas 3 plantillas, si la solicitud no es ajax.

Pero si la solicitud es ajax, contcactperson_detail_view devolverá la vista contcactperson_detail_view_ajax, que utiliza la plantilla contactperson_detail_ajax.html para la representación. Y esta plantilla es el siguiente:

<h1>{{ contactperson.first_name }} {{ contactperson.family_name }}</h1> 
{% include 'cms/contactperson_detail_photo.html' %}                           
{% include 'cms/contactperson_detail_textpane.html' %} 

por lo que utiliza los mismos sub-plantillas, pero no se está extendiendo nada, por tanto, sólo es necesario el marcado entregado. Como la vista ajax pasa is_ajax = True a la plantilla, se puede usar para ajustar cosas menores, como establecer atributos de identificación correctos.

No se necesita un procesador de contexto o url-conf adicional.

Finalmente el código Javascript:

$("#contact_person_portlet a").click(function(event){ 
     event.preventDefault(); 
     $.ajax({ 
      type: "GET", 
      url: event.target.getAttribute('href'), 
      success: function(msg){ 
       overlay(msg); 
      } 
     }); 
    }); 

la esperanza de que será útil para algunas personas. ¡Si es así, por favor deja un comentario!

+0

Creo que puede implementar una solución más simple al usar una vista única, y la misma plantilla para ajax/no-ajax, pero heredando de una plantilla base diferente dependiendo de una variable de contexto. Ver http://stackoverflow.com/questions/4014156/django-templates-sysntax-error/4018629#4018629 para un Reponse di a otra pregunta en esa línea –

+0

de hecho muy elegante – vikingosegundo

Cuestiones relacionadas