How pagination affects performance

I am working on a kind of medium-size website where we have many posts (when I say many I talk about millions of posts).

Because posts are shown to users according to their preferences; the list of posts changes for every user. We used a Digg style pagination with the paginators provided by django, but the problem was that those paginators perform “SELECT COUNT(*) …” queries and when you have complex querysets and many rows; that queries are really expensive, making the complete application very slow.

Since we knew in this case users don’t care about the total number of objects or pages there was no need to use that “counts” so we decided to use django endless pagination http://code.google.com/p/django-endless-pagination/ Now our database is not exhausted anymore and the site is very quick now. Also, the installation and configuration was so easy that just took some minutes.

I’m really glad these guys built endless pagination, you should definitely give it a try.

no puede seeeeeeeer Delfin unplugged

Getting Random objects from a Queryset in Django

When providing related or suggested info to the user in a website, it’s a common practice to obtain a random set of items. To do this in django the “usual” way is:

Book.objects.all().order_by('?')[:10]

The above code, sorts all books in a random order and then picks the first 10 objects. This approach is not really efficient en MySQL. Since the “ORDER BY ?” clause is really expensive. So, a good way to obtain random elemets (actually a random slice) is the following:

import random
count = Book.objects.all().count()
slice = random.random() * (count - 10)
Book.objects.all()[slice: slice+10]

The above code selects a random position for starting a slice (the next items are going to be consecutive). So it’s not really random.

Another approach is to get the random ids from Python:

from random import sample
count = Book.objecs.all().count()
rand_ids = sample(xrange(1, count), 10)
Book.objects.filter(id__in=rand_ids)

This last solution works fine for consecutive ids, where there are no missing elements. But you can always re call it until you have all the items you want.

Django render_to_response

It is important to see how django doesn’t automatically appends the context variables to the request object.

Say you want to access MEDIA_URL in your templates, using the following code will not work since the context is not created and it is not passed to the render_to_response function

def my_view(request):
    return render_to_response('my_template.html',
                              my_data_dictionary)

The first solution is to build the context and pass it to the render_to_response function, like this:

def my_view(request):
    return render_to_response('my_template.html',
                              my_data_dictionary,
                              context_instance=RequestContext(request))

But, this is kind of repetitive and boring. So a django snippet was proposed for that in http://www.djangosnippets.org/snippets/3/

from django.shortcuts import render_to_response
from django.template import RequestContext

def render_response(req, *args, **kwargs):
    kwargs['context_instance'] = RequestContext(req)
    return render_to_response(*args, **kwargs)

That works, But django just implemented almost the same thing in generic views. So, the solution I prefer is using the direct_to_template generic view

def my_view(request):
    # View code here...
    return direct_to_tempalte(request,
                                        template_name='my_template.html',
                                        extra_context=some_dict)

La taberna esta casi lista www.lataberna.pe

He venido trabajando con algunos amigos en un site peruano http://www.lataberna.pe para un pub . La verdad el site esta orientado por su simplicidad, hemos tenido muchas peleas sobretodo por cuestiones de diseño. Aunque no estoy del todo contento con el acuerdo final, creo que se acerca bastante a lo que yo buscaba.

El site se mantiene bastante simple al momento, comprar bebidas, ver fotografias de los clientes, ver los regalos que la compania ofrece entre otras cosas. Me hubiera gustado ver otras caracteristicas como comentarios y tags en las fotos, tal vez algun blog o actualizaciones de su pagina en twitter y facebook probablemente esten disponibles para futuras versiones.

Las lecciones aprendidas:

  1. Django siempre nos salva y nos ahorra un enorme tiempo de desarrollo
  2. Hacer mockups; nos falto hacer mockups para no tener tantas discusiones cuando las cosas ya estaba hechas
  3. Los usuairos tambien piensan: muchas veces no los consideramos y este es un gran error, gente que poco sabe de desarrollo da muy buenas ideas.
  4. Sorl thumbnails no solo hace thumbnails: por no leer la documentacion no sabiamos esto, ahora si notamos que sorl es bastante bueno
  5. Algunas veces Internet Explorer 6 no tiene la culpa: siempre le hecho la culpa de todo (y es que generalmente si la tiene), pero sucede que algunas veces nuestro firefox o internet explorer 7 “corrige alguno de nuestros errores” no es hasta que no validamos el html/css que nos damos cuenta que el error es nuestro.
  6. No necesitamos flash para hacer animaciones: muchas veces veo sitios web que tienen flash para cambiar algunas imagenes o hacer mas dinamicos sus banners. En realidad esto no es necesario ya que javascript lo puede hacer. Si bien es cierto era un poco mas trabajoso, ya no lo es tanto con los cientos de plugins que existen para jquery. Personalmente perfiero evitar el uso de flash en los websites

Bueno denle una mirada en http://www.lataberna.pe

ViaBCP

Hace unos dias tuve que ingresar al portal del banco de credito (www.viabcp.com) para hacer algunas transacciones y bueno como el site parece un poco antiguo y anticuado y yo tenia algo de tiempo libre me anime a revisar un poco el html del site. Aqui lo que encontre:

  • Al ingresar a http://www.viabcp.com.pe me redirecciona a http://www.viabcp.com/zona_publica/01_persona/index.html. Es esto necesario? por que una url tan compleja para el homepage? Igualmente la redireccion me parece algo brusca.
  • Si uno nota las urls del site, se da cuenta que son realmente feas y parecen no tener mucha coherencia entre si. Por ejemplo al hacer click sobre el tab “instituciones” la redireccion es a http://www.viabcp.com/zona_publica/09_banca/index.html esto me parece en extremo innecesario y mal organizado. zon publica???? es eso neceario???, 09_banca ??? entonces no deberia existir 08_banca??? por que todas sus paginas terminan en index.html es eso necesario?????
  • la cabecera y pie no cuadran con el ancho del contenido (ver la imagen al final del post)
  • Se usan tablas para el layout, el layout principal de la pagina se hace con tablas, lo que no es para nada elegante, incluso se incluyen tds para dar espacio entre columnas. Esto produce codigo html inentendible llegue a encontrar 4 tablas anidadas cuando ninguno de los elementos deberia era “tabulable”
  • CSS redundate, no se usan mucho las cascadas para generalizar algunos elementos
  • ninguno de sus links tiene el atributo title que es obligatorio
  • WTF? no hay doctype en la declaracion del documento, sera 1.0?? transitional??? strict???xhtml?
  • Se usan atributos y reglas que ya no deberian ser utilziadas (atributos de estilo como height width border en el html), como width para tablas en el html, etiquedas del tipo topmargin marginwidth marginheight entonces para que esta el css????
  • No se especifica el type en sus scripts
  • Existen scripts dentro del html (deberia ser mejor que los tengan afuera del documento)
  • Aunque no es vital, es una buena practica poner los scripts en la parte final del html, aqui estan principalmente en el head
  • Se usa
    nbsp;

    para saltos de linea

  • Los scripts de js tienen llaves confusas, la indentacion no siempre es corecta
  • existen tags script sin contenido
  • algunos tags estan con mayusculas y otros con minusculas (si es xhtml todos deberian ser minusculas pero como dije antes, no sabemos si es o no xhtml por que no hay doctype)
  • Hay tags con el atributo style, entonces para que tienen hojas de estilo externas?
  • las imagenes no tienen el atributo alt que es obligatorio
  • no existe ningun tipo de indentacion en el html generado
  • en el css todo se hace mediante clases y el nombre de las clases esta totalmente relacionado con el estilo, por ejemplo txt12naraAri, es para textos de tamanio 12 de color naranja en Arial. Y que pasa si quiero que sean helvetica azul??? tendria que cambiar el nombre de la clase y actualizar todos los elementos que la referencian????
  • el enlace a correoweb no funciona
  • el logo del banner del header deberia ser un link al homepage no? (no es necesario pero se estila hacer eso)
  • el site no funciona en absoluto (se muestra una pagina en blanco) si no se tiene javascript habilitado

Candidato presidencial

Un amigo me paso este tremendo link http://modestoerestu.blogspot.com/ Se trata de Modeto, un tio que quiere ser presidente. En su plancha presidencial propone a Optimus Chafloque con el lema “Peruanos Transormense y avanzen”

Recomiendo dar una revisada a sus afiches que son realmente buenos jajajajaja se nota que tiene un sentido del humor excepcional. Aqui una muestra

optimus

yatuve

New Django Rpx

Rpx is a great sig in center. With RPX users can login using their facebook, openid, google, myspace, aol, yahoo, blogger, flickr and some other types of accounts.

Some days ago I looked at django-rpx wich is pretty good but doesn´t cover som interesting rpx like mapping. Mapping allows a user to have multiple openids so if you don´t remeber what account to use for a specific site just register all your ids in the site and login with any of them. So I decide to create a brach of django-rpx callend django-newrpx

With this application you can use rpx sing very easy. You can add openids to your accoutns, and delete them. You can also retrive the list of all openids registered for a user in the rpx servers.

Give it a try

Trampa?

problemas-solucion

Using dynamic themes in django

I’ve been working on a django blogger clone. It has many interesting features includding email blogging, gadgets, followers, many authors per blog, feed agregation, fully customizable colors and themes.

This time I want to write how do we (I was working with a classmate) solved the problem of dynamic themes. First we wanted the themes to be dynamic that means the site administrator can add or edit themes using the django administration site.

First we created a model called Theme

class Theme(models.Model):
    name = models.CharField(max_length=40, unique=True)
    description = models.TextField(blank=True)
    slug = models.SlugField(max_length=50, unique=True, editable=False)
    base_html = models.FileField(upload_to=upload_to('themes/'))
    style_css = models.FileField(upload_to=upload_to('themes/'),
                                 blank=True, null=True)
    preview = models.ImageField(upload_to=upload_to('themes/'))

    def __unicode__(self):
        return '%s' % self.name

The name, description, preview and slug fields are obvious. We included a base_html file wich is supoused to be a base template used for all the weblog templates. A css style file is also needed for styling the weblog.

Many themes require adicional images so we created another model like this:

class ImageTheme(models.Model):
    theme = models.ForeignKey(Theme)
    image = models.ImageField(upload_to=upload_to_image('themes/'))
    

We expected each base.html to declare a content, and a sidebar block. So this blocks are used in the weblog templates to display the information.

The trick is to pass the tempalte name from the view. So the weblog tempaltes are going to inherit dynamically a base template but that is too much work so we created the following method in the blog model:

   def get_theme(self):
        if self.theme:
            location =  self.theme.base_html._get_url()
            name_list = location.split('/')
            s = len(name_list)
            return '%s/%s' % (name_list[s-2], name_list[s-1])
        return 'default_theme.html'

So in every weblog template we can have something like:

{% extends blog.get_theme %}

You also must tell template loaders where are your themes so maybe you can something like:

TEMPLATE_DIRS = (
    '/home/html/django_templates',
   '/path/to/your/templates/files/directory/',
)

in your settings.py

And remember that /path/to/your/templates/files/directory/ must be a directory inside your MEDIA_ROOT so django can upload the new themes there.