Best django questions in December 2010

What is the advantage of Class-Based views?

11 votes

I read today that Django 1.3 alpha is shipping, and the most touted new feature is the introduction of class-based views.
I've read the relevant documentation, but I find difficult to see the big advantage™ that I could get by using them, so I'm asking here for some help in understanding them.
Let's take an advanced example from the documentation.

urls.py

from books.views import PublisherBookListView

urlpatterns = patterns('',
    (r'^books/(\w+)/$', PublisherBookListView.as_view()),
)

views.py

from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher

class PublisherBookListView(ListView):

    context_object_name = "book_list"
    template_name = "books/books_by_publisher.html",

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
        return Book.objects.filter(publisher=self.publisher)

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super(PublisherBookListView, self).get_context_data(**kwargs)
        # Add in the publisher
        context['publisher'] = self.publisher
        return context

And now let's compare it to a “plain-old-views” solution, made by myself in 5 minutes for this question (I apologize for any error you may find in it).

urls.py

urlpatterns = patterns('books.views',
    url(r'^books/(\w+)/$', 'publisher_books_list', name="publisher_books_list"),
)

views.py

from django.shortcuts import get_object_or_404
from books.models import Book, Publisher

def publisher_books_list(request, publisher_name):
    publisher = get_object_or_404(Publisher, name__iexact=publisher_name)
    book_list = Book.objects.filter(publisher=publisher)

    return render_to_response('books/books_by_publisher.html', {
        "book_list": book_list,
        "publisher": publisher,
    }, context_instance=RequestContext(request))

The second version to me looks:

  • Equivalent in functionality
  • A lot more readable (self.args[0]? awful!)
  • Shorter
  • Not less DRY-compliant

Is there something big I'm missing? Why should I use them? Are those on the documentation? If so then what would be the ideal use case? Are mixins that useful?

Thanks in advance to anybody who contributes!

P.S. for those who might wonder, I was never enthralled by generic views as well: as soon as I needed some advanced functionality, they became no shorter than regular views.

You can subclass a class and refine methods like get_context_data for specific cases, and leave the rest as-is. You can't do that with functions.

For instance, you might need to create a new view that does everything a previous one does, but you need to include extra variable in the context. Subclass the original view and override the get_context_data method.

Also, separating the steps needed to render the template into separate methods promotes clearer code - the less done in a method, the easier it is to understand. With regular view functions, it's all dumped into the one processing unit.

Django vs web2py for a beginner developer

10 votes

Which of these two frameworks is better suited to a developer with 11 months experience. I have decided to learn python for my server side coding and wanted to know which of these would be better suited for someone at my skill level. I have just spent a few days playing around with web2py and really like it and i am wondering if Django offers something more that i am missing out on?

PS. UPDATE: Thank you all for the wonderful input, after buying three django books and going through a few small projects/tutorials for both django and web2py, i have settled on web2py. This is a wonderful framework, which makes web development really fun for a newbe. I would recommend all newbies to learn this framework as it will be mainstream in the future. Django is also a wonderful framework but web2py is just better in my limited experience opinion.

(disclamer: I am the project leader for web2py)

Django has been around 5 years longer than web2py therefore it has more users and more applications to show off. Django has what they call "admin" which is not the same as web2py's "admin" but more like web2py's "appadmin". Django's "admin" is better and more customizable than web2py's "appadmin". Django does not have the equivalent of web2py's "admin". (sorry for the name confusion).

web2py is more compact and has more functionality out of the box (more supported databases, web based IDE, ticketing system, runs on GAE without patches, multiple login methods, role based access control, web based translation interface, support for multiple database connections, distributed transactions, and more).

For me the most important functionality of web2py is automatic migrations. Django does not provide them out of the box.

For web2py long term backward compatibility is a primary goal, together with security. Django is comparable to web2py in terms of security (except that web2py had CSRF prevention and default escaping in templates before they did) but Django broke backward compatibility when 1.0 was released. web2py never did since Oct 2007.

To me the web2py syntax is more natural:

 db(db.tablename.fieldname<=value).select() # web2py
 Tablename.objects.filter(fieldname__lt==value) # Django

I am not aware of any functionality of web2py that is not present in Django. I have asked that question many times because, if there is, we want to add it to web2py, but I have not yet received a satisfactory answer.

Of course there are things that we both do but differently. Django follows "explicit is better than implicit". web2py does not and instead follows "everything should have a default behavior". I believe this makes web2py code more compact.

Anyway, whatever you choose, they are too good solid web frameworks and the similarities are less than the differences. The Django developers are very smart people.

The web2py community is very friendly. You should try ask a question on the web2py google group and on the Django group. Just as an experiment.

Huge Django Session table, normal behaviour or bug?

7 votes

Perhaps this is completely normal behaviour, but I feel like the django_session table is much larger than it should have to be.

First of all, I run the following cleanup command daily so the size is not caused by expired sessions:

DELETE FROM %s WHERE expire_date < NOW()

The numbers:

  • We've got about 5000 unique visitors (bots excluded) every day.
  • The SESSION_COOKIE_AGE is set to the default, 2 weeks
  • The table has a little over 1,000,000 rows

So, I'm guessing that Django also generates session keys for all bots that visits the site and that the bots don't store the cookies so it continuously generates new cookies.

But... is this normal behaviour? Is there a setting so Django won't generate sessions for anonymous users, or atleast... no sessions for users that aren't using sessions?

Is it possible for robots to access any page where you set anything in a user session (even for anonymous users), or any page where you use session.set_test_cookie() (for example Django's default login view in calls this method)? In both of these cases a new session object is created. Excluding such URLs in robots.txt should help.

In the spirit of this question, I would like to know if anyone has any tips on creating a useful and "complete" test suite (can a test suite ever be "complete"?) for a Django webapp.

My situation: I've knocked out a prototype and am now working on adding some regression testing. I personally use django-webtest for most of my tests with some URL testing using the Django test client.

II do not feel comfortable with my test suite at all. I am far from a testing pro so trying to improve on that end. Any tips---whether applicable in my situation or not---would be greatly appreciated.

I would recommend reading Django 1.1 Testing and Debugging by Karen M. Tracey. The first five chapters cover testing in Django. Specifically, you should look at Chapter 5 which discusses integrating other test tools. Below is an excerpt of what Chapter 5 covers:

In this chapter, we:

  • Learned what hooks Django provides for adding test functions
  • Saw an example of how these hooks can be used, specifically in the case of adding code coverage reporting
  • Also explored an example where using these hooks was not necessary—when integrating the use of the twill test tool into our Django test cases

Here are links to some of the tools that Karen Tracey discusses in chapter 5 of her book:

Lettuce

You may also want to check out Lettuce. From the website:

Lettuce is a very simple BDD tool based on the Cucumber.

The Lettuce documentation also has a section on integrating Lettuce with Django.

django class-based views with inline model-form or formset

7 votes

Hi!

I have the following models:

class Bill(models.Model):
    date = models.DateTimeField(_("Date of bill"),null=True,blank=True)

class Item(models.Model):
    name = models.CharField(_("Name"),max_length=100)
    price = models.FloatField(_("Price"))
    quantity = models.IntegerField(_("Quantity"))
    bill = models.ForeignKey("Bill",verbose_name=_("Bill"),
                             related_name="billitem")

I know that this is possible:

from django.forms.models import inlineformset_factory
inlineformset_factory(Bill, Item)

and then process this via standard view.

Now I was wondering, if there is a way to achieve the same (meaning: using a inline for adding/editing items belonging to a bill) using class based views (not for the admin-interface).

I red the generic source code of the 1.3-beta-1 :

The code is absolutely not ready for List editing or there is some black magic here. But I think that it can be implemented quickly.

If you look at the django.view.generic.edit (that support detailed object editing) module how it use the django.view.generic.detail module.

I think that a django.view.generic.list_edit module can be implemented using django.view.generic.list and some part from django.view.generic.edit.

How to implement an "undo" feature using Python/Django

6 votes

I have a Django application where I allow a user to import a CSV file with contact data (membership #, first name, last name, etc).

When they import the file, the application checks the database for a matching record and either: 1) inserts a new record if no match exists, or 2) updates the existing data with the new data.

My question is: what is the best way to implement an undo feature, using Django or straight Python, so that a user can undo the import operation and revert multiple records back to their original state?

My initial thoughts are to create a table like this (pseudo code):

Table HISTORY
   unique_id
   record_affected_id
   old_value
   new_value

Then if the user clicks "Undo" I can look up the unique_id that's associated with their transaction and set every record affected by that transaction to the old_value.

I'm wondering if there's a simpler way to do this that I'm missing, or if anyone has experience with something like this.

Take a look at django-reversion. It provides version control for Django models. Can be easily added to existing project.

It doesn't employ "current" pointer approach. Instead, it serializes object each time it's being saved and stores it in a separate Version model with generic foreign key pointing to this object. (Relationship fields are serialized as primary keys by default.) Also, it allows to group Versions into Revisions in a flexible way.

So you can do something like that:

  • When user uploads CSV, just save changes as usual, but add @revision.create_on_success decorator to the function which does the import—so that any changes to records made by that function will be stored under a single revision.
  • When user hits "Undo", you just revert the latest revision.

Here's how it could be done::

@revision.create_on_success
def import_csv(request, csv):
    # Old versions of all objects save()d here will
    # belong to single revision.

def undo_last_csv_import(request):
    # First, get latest revision saved by this user.
    # (Assuming you create revisions only when user imports a CSV
    # and do not version control other data.)
    revision = Revision.objects.filter(user=request.user)\
        .order_by('-date_created')[0]
    # And revert it, delete=True means we want to delete
    # any newly added records as well
    revision.revert(delete=True)

It relies on the fact that you create revisions only when user imports CSVs. That means, if you plan to also version control other data, then you'll need to implement some kind of a flag by which you can get records affected by the latest import. Then you can get a record by this flag, get it latest saved version, and revert the whole revision that version belongs to. Like this::

def undo_last_csv_import(request):
    some_record = Record.objects.by_user(request.user).from_the_last_import()[0]
    latest_saved_version_of_some_record = Version.objects.get_for_date(
        some_record,
        datetime.now(), # The latest saved Version at the moment.
        )
    # Revert all versions that belong to the same revision
    # as the version we got above.
    latest_saved_version_of_some_record.revision.revert()

It's not a beautiful solution, there most certainly are ways to do it better with this app. I recommend to take a look at the code to understand better how does django-reversion work—very well documented, couldn't find a function without a docstring. ^_^d

(Documentation is also good, but turned out to be a bit misleading for me, i.e. they write Version.objects.get_for_date(your_model, date), where your_model is actually a model instance.)

Update: django-reversion is actively maintained, so don't rely on the code above much, and better check their wiki on how to manage versions & revisions outside django's admin. For instance, revision comments are already supported, that may simplify things a bit.

Django Project Done and Working. Now What?

6 votes

Hi,

I just finished what I would call a small django project and pretty soon it's going live. It's only 6 models but a fairly complex view layer and a lot of records saving and retrieving.

Of course, forgetting the obvious huge amount of bugs that will, probably, fill my inbox to the top, what would it be the next step towards a website with best performance. What could be tweaked?

I'm using jmeter a lot recently and feel confident that I have a good baseline for future performance comparisons, but the thing is: I'm not sure what is the best start, since I'm a greedy bastard that wants to work the least possible and gather the best results.

For instance, should I try an approach towards infrastructure, like a distributed database, or should I go with the code itself and in that case, is there something that specifically results in better performance? In your experience, whats pays off more?

As a personal contribution: I sometimes have the impression that some operations, when done through django's signals, are faster then the usual view way. But hey, I'm biased. I freaking loooove signals. :)

Personal anecdotes like mine, are welcome as a way to stimulate some research, but some fact based opinions are much more appreciated. :)

Thanks very much.

here is what we did...

  1. used django-debug-toolbar to analyze performance of each page (# of queries and response times)
  2. used Django cache framework...most importantly memcache
  3. used Firebug's pagespeed to optimize HTTP page loads
  4. used Google Analytics for general site usage stats (find out what's being used)
  5. used Apache HTTP server benchmarking tool for quick performance stats

In general, don't try to optimize performance up front. First, collect usage/performance stats, then pick off the most rewarding changes (effort vs. benefit) until you get decent results. The goal should be to avoid unnecessary complexity (distributed databases, etc)

Then, if you still aren't happy, consider these (in order): more RAM (goes a long way), a dedicated database server, load balancing multiple app servers (using perlbal, etc), a dedicated media server, etc...see these for more details (deployment guide, performance tips)

good luck...

django staticfiles app help

6 votes

Hay, I've having a little issue with django's staticfiles app.

I have added

'django.contrib.staticfiles',

to my INSTALLED_APPS

and have added

STATIC_URL = '/static/'
STATIC_ROOT = '/Users/kevdotbadger/django/mylook/static/'

to my settings.py file.

All my static files are located within the STATIC_ROOT folder on my mac.

Now, within my template i use

{{ STATIC_URL }}

which correctly renders to /static/

However

{{ STATIC_URL }}css/style.css

gives the server a 404 error. I'm using the 'runserver' command as the server.

Is there something I'm missing?

Thanks

The problem you're having is the same problem I was having when I first started using 1.3. The staticfiles.views.serve method of serving static files will verify that the requested file can be found in a directory listed in your STATICFILES_DIRS setting (or through one of the finders listed in STATICFILES_FINDERS).

What you did was what I did, which is put your actual static files in your STATIC_ROOT, and that's the problem. Django recommends you do not put your actual static files in there, but instead in another location, and use the collectstatic management command to find all of your static files and bundle them up under STATIC_ROOT

The easiest solution in your case (and admittedly, the solution I used as well), was to add STATIC_ROOT to my STATICFILES_DIRS setting:

STATICFILES_DIRS = (STATIC_ROOT,)

What this does is make it so that when the staticfiles app tries to serve the requested file, it's able to locate it in STATIC_ROOT

Making moves w/ websockets and python / django ( / twisted? )

5 votes

The fun part of websockets is sending essentially unsolicited content from the server to the browser right?

Well, I'm using django-websocket by Gregor Müllegger. It's a really wonderful early crack at making websockets work in Django.

I have accomplished "hello world." The way this works is: when a request is a websocket, an object, websocket, is appended to the request object. Thus, I can, in the view interpreting the websocket, do something like:

request.websocket.send('We are the knights who say ni!')

That works fine. I get the message back in the browser like a charm.

But what if I want to do that without issuing a request from the browser at all?

OK, so first I save the websocket in the session dictionary:

request.session['websocket'] = request.websocket

Then, in a shell, I go and grab the session by session key. Sure enough, there's a websocket object in the session dictionary. Happy!

However, when I try to do:

>>> session.get_decoded()['websocket'].send('With a herring!')

I get:

Traceback (most recent call last):
File "<console>", line 1, in <module>
error: [Errno 9] Bad file descriptor

Sad. :-(

OK, so I don't know much of anything about sockets, but I know enough to sniff around in a debugger, and lo and behold, I see that the socket in my debugger (which is tied to the genuine websocket from the request) has fd=6, while the one that I grabbed from the session-saved websocket has fd=-1.

Can a socket-oriented person help me sort this stuff out?

Hi Justin, I'm the author of django-websocket. I'm not a real expert in the topic of websockets and networking, however I think I have a decent understanding of whats going on. Sorry for going into great detail. Even if most of the answer isn't specific to your question it might help you at some other point. :-)


How websockets work

Let me explain shortly what a websocket is. A websocket starts as something that really looks like a plain HTTP request, established from the browser. It indicates through a HTTP header that it wants to "upgrade" the protocol to be a websocket instead of a HTTP request. If the server supports websockets, it agrees on the handshake and both - server and client - now know that they will use the established tcp socket formerly used for the HTTP request as a connection to interchange websocket messages.

Beside sending and waiting for messages, they have also of course the ability to close the connection at any time.

How django-websocket abuses the python's wsgi request environment to hijack the socket

Now lets get into the details of how django-websocket implements the "upgrading" of the HTTP request in a django request-response cylce.

Django usually uses the WSGI specification to talk to the webserver like apache or gunicorn etc. This specification was designed just with the very limited communication model of HTTP in mind. It assumes that it gets a HTTP request (only incoming data) and returns the response (only outgoing data). This makes it tricky to force django into the concept of a websocket where bidirectional communication is allowed.

What I'm doing in django-websocket to achieve this is that I dig very deeply into the internals of WSGI and django's request object to retrieve the underlaying socket. This tcp socket is then used to handle the upgrade the HTTP request to a websocket instance directly.

Now to your original question ...

I hope the above makes it obvious that when a websocket is established, there is no point in returning a HttpResponse. This is why you usually don't return anything in a view that is handled by django-websocket.

However I wanted to stick close to the concept of a view that holds the logic and returns data based on the input. This is why you should only use the code in your view to handle the websocket.

After you return from the view, the websocket is automatically closed. This is done for a reason: We don't want to keep the socket open for an undefined amount of time and relying on the client (the browser) to close it.

This is why you cannot access a websocket with django-websocket outside of your view. The file descriptor is then of course set to -1 indicating that its already closed.

Disclaimer

I explained above that I'm digging in the surrounding environment of django to get somehow -- in a very hackish way -- access to the underlaying socket. This is very fragile and also not supposed to work since WSGI is not designed for this! I also explained above that the websocket is closed after the view ends - however after the websocket closed down (AND closed the tcp socket), django's WSGI implementation tries to send a HTTP response - it doesn't know about websockets and thinks it is in a normal HTTP request-response cycle. But the socket is already closed an the sending will fail. This usually causes an exception in django.

This didn't affected my testings with the development server. The browser will never notice (you know .. the socket is already closed ;-) - but raising an unhandled error in every request is not a very good concept and may leak memory, doesn't handle database connection shutdown correctly and many athor things that will break at some point if you use django-websocket for more than experimenting.

This is why I would really advise you not to use websockets with django yet. It doesn't work by design. Django and especially WSGI would need a total overhaul to solve these problems (see this discussion for websockets and WSGI). Since then I would suggest using something like eventlet. Eventlet has a working websocket implementation (I borrowed some code from eventlet for the initial version of django-websocket) and since its just plain python code you can import your models and everything else from django. The only drawback is that you need a second webserver running just to handle websockets.

How does python load all the values in sys.path?

5 votes

Hi all, I'm a python beginner and I'm in my first days playing with my own python scripts and projects such as django.

I use Ubuntu and I set my PYTHONPATH as

export PYTHONPATH=/usr/lib/python2.6:~/Projects/mypython 

When I run into a python interpreter

import sys
print sys.path

I can see

['', '/usr/bin', '/usr/local/lib/python2.6/dist-packages/ropemode-0.1_rc2-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/rope-0.9.3-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/ropevim-0.3_rc-py2.6.egg', '/usr/lib/python2.6', '/home/jaume/Projects/mypython', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/local/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages/PIL', '/usr/lib/python2.6/dist-packages/gst-0.10', '/usr/lib/pymodules/python2.6', '/usr/lib/python2.6/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.6/gtk-2.0', '/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode', '/usr/lib/pymodules/python2.6/IPython/Extensions', u'/home/jaume/.ipython']

How does python load all the non-PYTHONPATH paths? Is there any index? Moreover, I have my django installed at /usr/lib/pymodules and, even it's not in the sys.path list, it runs.

Many thanks.

This is a list of every file the Python interpreter on my computer (which is set up similar to, but not the same as, yours) opens before it starts running code provided by me:

$ strace -eopen python -c 1 2>&1 | grep -ve '-1 E'
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/libpthread.so.0", O_RDONLY)  = 3
open("/lib/libdl.so.2", O_RDONLY)       = 3
open("/lib/libutil.so.1", O_RDONLY)     = 3
open("/usr/lib/libssl.so.0.9.8", O_RDONLY) = 3
open("/usr/lib/libcrypto.so.0.9.8", O_RDONLY) = 3
open("/usr/lib/libz.so.1", O_RDONLY)    = 3
open("/lib/libm.so.6", O_RDONLY)        = 3
open("/lib/libc.so.6", O_RDONLY)        = 3
open("/proc/meminfo", O_RDONLY)         = 3
open("/usr/lib/python2.6/site.py", O_RDONLY) = 3
open("/usr/lib/python2.6/site.pyc", O_RDONLY) = 4
open("/usr/lib/python2.6/os.py", O_RDONLY) = 4
open("/usr/lib/python2.6/os.pyc", O_RDONLY) = 5
open("/usr/lib/python2.6/posixpath.py", O_RDONLY) = 5
open("/usr/lib/python2.6/posixpath.pyc", O_RDONLY) = 6
open("/usr/lib/python2.6/stat.py", O_RDONLY) = 6
open("/usr/lib/python2.6/stat.pyc", O_RDONLY) = 7
open("/usr/lib/python2.6/genericpath.py", O_RDONLY) = 6
open("/usr/lib/python2.6/genericpath.pyc", O_RDONLY) = 7
open("/usr/lib/python2.6/warnings.py", O_RDONLY) = 6
open("/usr/lib/python2.6/warnings.pyc", O_RDONLY) = 7
open("/usr/lib/python2.6/linecache.py", O_RDONLY) = 7
open("/usr/lib/python2.6/linecache.pyc", O_RDONLY) = 8
open("/usr/lib/python2.6/types.py", O_RDONLY) = 7
open("/usr/lib/python2.6/types.pyc", O_RDONLY) = 8
open("/usr/lib/python2.6/UserDict.py", O_RDONLY) = 5
open("/usr/lib/python2.6/UserDict.pyc", O_RDONLY) = 6
open("/usr/lib/python2.6/_abcoll.py", O_RDONLY) = 6
open("/usr/lib/python2.6/_abcoll.pyc", O_RDONLY) = 7
open("/usr/lib/python2.6/abc.py", O_RDONLY) = 7
open("/usr/lib/python2.6/abc.pyc", O_RDONLY) = 8
open("/usr/lib/python2.6/copy_reg.py", O_RDONLY) = 5
open("/usr/lib/python2.6/copy_reg.pyc", O_RDONLY) = 6
open("/usr/local/lib/python2.6/dist-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/python2.6/dist-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/python2.6/dist-packages/PIL.pth", O_RDONLY) = 4
open("/usr/lib/python2.6/dist-packages/pygst.pth", O_RDONLY) = 4
open("/usr/lib/python2.6/dist-packages/python-support.pth", O_RDONLY) = 4
open("/usr/lib/python2.6/dist-packages/wx.pth", O_RDONLY) = 4
open("/usr/lib/python2.6/dist-packages/zope.interface-3.5.3-nspkg.pth", O_RDONLY) = 4
open("/usr/lib/python2.6/sitecustomize.py", O_RDONLY) = 4
open("/usr/lib/python2.6/sitecustomize.pyc", O_RDONLY) = 5
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
open("/usr/lib/python2.6/encodings/__init__.py", O_RDONLY) = 3
open("/usr/lib/python2.6/encodings/__init__.pyc", O_RDONLY) = 4
open("/usr/lib/python2.6/codecs.py", O_RDONLY) = 4
open("/usr/lib/python2.6/codecs.pyc", O_RDONLY) = 5
open("/usr/lib/python2.6/encodings/aliases.py", O_RDONLY) = 4
open("/usr/lib/python2.6/encodings/aliases.pyc", O_RDONLY) = 5
open("/usr/lib/python2.6/encodings/utf_8.py", O_RDONLY) = 3
open("/usr/lib/python2.6/encodings/utf_8.pyc", O_RDONLY) = 4

All of these could, at least potentially, have an effect on sys.path. It is extremely unlikely that the stuff that comes before site.py would, however (those are all OS libraries and interfaces not specific to Python). I'd suggest you take a hard look at site.py, sitecustomize.py, and the various .pth files (your list of .pth files will be different than mine; that's normal).

Good examples of open source Google App Engine Django projects

5 votes

I am looking for a good example of a Django / python based Google App Engine app to use a learning tool.

I have seen some of the other posts and they are mainly Java based and not really what I am looking for.

Any advice?

Thank you in advance,

Kent

Hello,

Jaiku and Code Review are two good examples of opensource projects run with GAE/Django.

Test if a celery task is still being processed

4 votes

How can I test if a task (task_id) is still processed in celery? I have the following scenario:

  1. Start a task in a Django view
  2. Store the BaseAsyncResult in the session
  3. Shutdown the celery daemon (hard) so the task is not processed anymore
  4. Check if the task is 'dead'

Any ideas? Can a lookup all task being processed by celery and check if mine is still there?

define a field (PickledObjectField) in your model to store the celery task:

class YourModel(models.Model):
    .
    .
    celery_task = PickledObjectField()
    .
    .

    def task():
        self.celery_task = SubmitTask.apply_async(args = self.task_detail())
        self.save()

In case your task is not specific on any model you should create one specifically for the celery tasks.

or else I suggest using django-celery. It has a nice monitoring feature:
http://ask.github.com/celery/userguide/monitoring.html#django-admin-monitor, saves the tasks details in a django model in a nice graphical way.

Should I use wtforms with Pylons?

4 votes

I am migrating my django project to pylons and am up to form validations. Is the builtin formencode module sufficient for form validation or is WTforms a "better" option? What would be the advatanges of using wtforms?

I chose sqlalchemy as the orm backend so something that plays nicely with that would be nice too.

WTForms is very similar to django forms. If you are migrating you should probably use it to speedup your migration.

Renaming an app with Django and South

4 votes

I am renaming an application to a more suitable name. In doing so, I want to ensure that South properly migrates the database (renames database tables and changes references in django_content_type or south_migrationhistory). I know how to migrate a model to a different app, but when I try rename the app itself, South does not recognize the migration history properly.

Undesirable solution: In renaming old_app to new_app I could leave old_app/migrations intact and add new migrations to this directory to migrate the database to reference new_app.

If possible I would prefer to delete the directory old_app entirely. I have not yet thought of a better solution to this problem.

What is the best way to rename an app with Django South without losing data?

I wouldn't mess with the app names. You refer to the app names literally everywhere. URL confs, settings, other apps, templates etc.

The way django is designed, correspondingly south, assumes there is no need to change the app names. - name your projects what you want. You don't refer to it anywhere. Changing app names is cumbersome. Your undesirable solution is the best solution I see, if you really want to rename your app.

For what it is worth, you can always use the python import as to import the app in a different name, if you so desire.

Using .aggregate() on a value introduced using .extra(select={...}) in a Django Query?

4 votes

I'm trying to get the count of the number of times a player played each week like this:

player.game_objects.extra(
    select={'week': 'WEEK(`games_game`.`date`)'}
).aggregate(count=Count('week'))

But Django complains that

FieldError: Cannot resolve keyword 'week' into field. Choices are: <lists model fields>

I can do it in raw SQL like this

SELECT WEEK(date) as week, COUNT(WEEK(date)) as count FROM games_game
WHERE player_id = 3
GROUP BY week

Is there a good way to do this without executing raw SQL in Django?

You could use a custom aggregate function to produce your query:

WEEK_FUNC = 'STRFTIME("%%%%W", %s)' # use 'WEEK(%s)' for mysql

class WeekCountAggregate(models.sql.aggregates.Aggregate):
    is_ordinal = True
    sql_function = 'WEEK' # unused
    sql_template = "COUNT(%s)" % (WEEK_FUNC.replace('%%', '%%%%') % '%(field)s')

class WeekCount(models.aggregates.Aggregate):
    name = 'Week'
    def add_to_query(self, query, alias, col, source, is_summary):
        query.aggregates[alias] = WeekCountAggregate(col, source=source, 
            is_summary=is_summary, **self.extra)


>>> game_objects.extra(select={'week': WEEK_FUNC % '"games_game"."date"'}).values('week').annotate(count=WeekCount('pk'))

But as this API is undocumented and already requires bits of raw SQL, you might be better off using a raw query.