views:

39

answers:

1

So I am trying to emulate google app's status page: http://www.google.com/appsstatus#hl=en but for backups for our own servers. Instead of service names on the left it'll be server names but the dates and hopefully the pagination will be there too. My models look incredibly similar to this:

from django.db import models

STATUS_CHOICES = (
    ('UN', 'Unknown'),
    ('NI', 'No Issue'),
    ('IS', 'Issue'),
    ('NR', 'Not Running'),
)

class Server(models.Model):
    name = models.CharField(max_length=32)

    def __unicode__(self):
        return self.name

class Backup(models.Model):
    server = models.ForeignKey(Server)
    created = models.DateField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='UN')
    issue = models.TextField(blank=True)

    def __unicode__(self):
        return u'%s: %s' % (self.server, self.get_status_display())

My issue is that I am having a hell of a time displaying the information I need. Everyday a little after midnight a cron job will run and add a row for each server for that day, defaulting on status unknown (UN).

My backups.html:

{% extends "base.html" %}
{% block content %}
<table>
    <tr>
        <th>Name</th>
{% for server in servers %}
        <th>{{ created }}</th>
    </tr>
    <tr>
        <td>{{ server.name }}</td>
        {% for backup in server.backup_set.all %}
        <td>{{ backup.get_status_display }}</td>
        {% endfor %}

    </tr>
{% endfor %}
</table>
{% endblock content %}

This actually works but I do not know how to get the dates to show. Obviously {{ created }} doesn't do anything but the servers don't have create dates. Backups do and because it's a cron job there should only be X number of rows with any particular date (depending on how many servers we are following for that day).

Summary

I want to create a table, X being server names, Y being dates starting at today while all the cells being the status of a backup. The above model and template should hopefully give you an idea what my thought process but I am willing to alter anything. Basically I am create a fancy excel spreadsheet.

A: 

I suggest adding a function to get the dates you want to show, that's independent of a Server instance. Then you can use it both to get the recent backups and to get the dates for the header. In models.py:

from django.db import models
import datetime

def recent_dates():
    return [datetime.date.today() - datetime.timedelta(days=days) 
            for days in range(-6, 1)]

class Server(models.Model):
    ...
    def backup_for_date(self, date):
        next_date = date + datetime.timedelta(days=1)
        return self.backup_set.get(created__gte=date, created__lt=next_date)

    def recent_backups(self):
        return [self.backup_for_date(date) for date in recent_dates()]

Then, if you use the function in views.py:

from django.shortcuts import render_to_response
from myapp.models import Server, recent_dates

def status(request):
    servers = Server.objects.all()
    return render_to_response('status.html', 
        {'dates': recent_dates(), 'servers': servers}
    )

...you can use the recent_dates variable to print the headers in the template:

{% extends "base.html" %}
{% block content %}
<table>
    <tr>
        <th>Name</th>
        {% for date in recent_dates %}
        <th>{{ date }}</th>
        {% endfor %}
    </tr>
    {% for server in servers %}
    <tr>
        <td>{{ server.name }}</td>
        {% for backup in server.recent_backups() %}
        <td>{{ backup.get_status_display }}</td>
        {% endfor %}
    </tr>
    {% endfor %}
</table>
{% endblock content %}

Using this method also makes sure the cells don't get shifted out of position if data is missing. The code I provided will raise an exception in the call to the get() method inside backup_for_date() if data is missing, but backup_for_date() could easily be modified to return None in that case.

Ben Atkin