Archive for July, 2006

Comfortable development mode in Django

Friday, July 28th, 2006

If you run django in development mode, you need to tell it to serve static files by itself. If you use django in production mode, your http-deamon should handle that for you. You can automate the switchover by an appropriate urls.py setting:

from django.conf.urls.defaults import *
from django.conf import settings

urlpatterns = patterns('',
    (r'^admin/',    include('django.contrib.admin.urls')),
    (r'^r/',       include('django.conf.urls.shortcut')),
    (r'^comments/', include('django.contrib.comments.urls.comments')),
[...]
)

if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^media/(?P.*)$',
            'django.views.static.serve', {'document_root': '../media'}),
    )

Wednesday, July 26th, 2006

Sunday, July 23rd, 2006

Fehler fehlerfrei melden

Saturday, July 22nd, 2006

Wenn man einen Fehler meldet, will man, dass dieser schnell behoben wird. Aber zum Beheben müssen andere verstehen, was passiert ist und was eigentlich hätte passieren sollen. Das ist oft recht schwierig, weil die Person, die den Fehler meldet in Ihrem konkreten Arbeitsablauf steckt und implizit voraussetzt, dass der andere auch um die Situation weis, in der der Fehler passiert ist.

Wenn man folgenden Fragen beantwortet, hat man fast immer alle nötigen Fakten für einen guten Fehlerreport zusammen.

1. Was wollte ich erreichen?
2. Was habe ich gemacht?
3. Was habe ich erwartet, was daraufhin passieren sollte?
4. Was ist stattdessen passiert?
5. Wann ist das passiert?

Bei Sachen, die mit dem Internet zu tun haben sollte man auch immer alle URLs (das mit ‘http://’ vorne), die in dem Zusammenhang aufgetaucht sind nennen.

Beispiel:

Ich habe heute um 9:34h (5.) versucht, den Inhalt der Nasenschoner Produktseite ändern (1). Dazu habe ich auf den Link http://www.example.com/admin/news/newsitems/ aus Ihrer Email von 4.5.2006 geklickt (2). Aber anstatt eines Formulars zum Bearbeiten der Daten (3) kam eine Seite mit der Meldung “Datei nicht gefunden”. (4)

Siehe auch hier und hier.

Saturday, July 22nd, 2006

Setting the Last-Modified on a page served by django is not elegant but necessary for good HTTP-Citizenship.

An approach to this problem is like this:

def homepage(request):
  latest_news = NewsItem.objects.order_by('-created_at')[:5]
  response = render_to_response('news/homepage.html',
    {'latest': latest_news}, context_instance=RequestContext(request))
  response['Last-Modified'] = \
    latest_news[0].created_at.strftime('%a, %d %b %Y %H:%M:%S GMT')
  return response

Getting the right bins of the shelf

Saturday, July 8th, 2006

I currently have the pleasureof writing a warehouse managment system (using Djangos OR mapper – in case you care).

The warehouse has the concept of bins (e.g. Pallet) containing products. A bin typically contains between 1 (think fitness bike) and 3000 (think dart flys) products. Of the same product there are bins with different quantities of products available. The total number of bins with a product can be up to several hundreds.

One of the non-trivial issues is choosing the bins which allow to fullfill an order without repacking. So lets say I get an order for 300 Skateboards. I have one Pallet with 100 Skateboards, 3 with 80, 1 with 45, 3 with 25, 3 with 10, 2 with 2 and 2 with 1. This can be modelled as a list: [100, 80, 80, 80, 45, 25, 25, 25, 10, 10, 10, 2, 2, 2, 2, 2, 1, 1]

Turns out a quite simple and reasonable fast algorythm can find an acceptable solution:

>>> def find_fitting(items, n):
...   def _fittings(items, n):
...     for i in xrange(len(items)):
...       if items[i] == n:
...         yield [items[i]]
...       if items[i] <= n:
...         for cc in _fittings(items[:i]+items[i+1:],\
                n - items[i]):
...           yield [items[i]]+cc
...
...   items.sort()
...   items.reverse() # we prefer bigger bins
...   if sum(items) >> find_fitting([100, 80, 80, 80, 45, 25, 25, 25, \
                  10, 10, 10, 2, 2, 2, 2, 2, 1, 1], 300)
[100, 80, 80, 25, 10, 2, 2, 1]

WTF?

Saturday, July 8th, 2006
FAILED (failures=1)
Traceback (most recent call last):
[...]
AssertionError: [] != []