feedThe Django community aggregator

Simon Willison: Cache Machine: Automatic caching for your Django models

Cache Machine: Automatic caching for your Django models. This is the third new ORM caching layer for Django I've seen in the past month! Cache Machine was developed for zamboni, the port of addons.mozilla.org to Django. Caching is enabled using a model mixin class (to hook up some post_delete hooks) and a custom caching manager. Invalidation works by maintaining a "flush list" of dependent cache entries for each object-this is currently stored in memcached and hence has potential race conditions, but a comment in the source code suggests that this could be solved by moving to redis.

01 Jan 1970 12:00am GMT

Simon Willison: Announcing django-cachebot

Announcing django-cachebot. The ORM caching space around Django is heating up. django-cachebot is used in production at mingle.com and takes a more low level approach to cache invalidation than Johnny Cache, enabling you to specifically mark the querysets you wish to cache and providing some advanced options for cache invalidation. Unfortunately it currently relies on a patch to Django core to enable its own manager.

01 Jan 1970 12:00am GMT

Peter Bengtsson: Speed test between django_mongokit and postgresql_psycopg2

Following on from yesterday's blog about How and why to use django-mongokit I extended the exampleproject which is inside the django-mongokit project with another app called exampleapp_sql which does the same thing as the exampleapp but does it with SQL instead. Then I added a very simple benchmarker app in the same project and wrote three functions:

  1. One to create 10/100/500/1000 instances of my class
  2. One to edit one field of all 10/100/500/1000 instances
  3. One to delete each of the 10/100/500/1000 instances


[325 more words]

01 Jan 1970 12:00am GMT

Peter Bengtsson: How and why to use django-mongokit (aka. Django to MongoDB)

How and why to use django-mongokit Here I'm going to explain how to combine Django and MongoDB using MongoKit and django-mongokit.

MongoDB is a document store built for high speed and high concurrency with a very good redundancy story. It's an alternative to relational databases (e.g. MySQL) that is what Django is tightly coupled with in it's ORM (Object Relation Mapping) and what it's called now is ODM (Object Document Mapping) in lack of a better acronym. That's where MongoKit comes in. It's written in Python and it connects to the MongoDB database using a library called pymongo and it turns data from the MongoDB and turns it into instances of classes you have defined. MongoKit has nothing to do with Django. That's where django-mongokit comes in. Written by yours truly.


[1551 more words]

01 Jan 1970 12:00am GMT

Josh VanderLinden: Python And Execution Context

I recently found myself in a situation where knowing the execution context of a function became necessary. It took me several hours to learn about this functionality, despite many cleverly-crafted Google searches. So, being the generous person I am, I want to share my findings.
My particular use case required that a function behave differently depending on whether it was called in an exec call. Specifics beyond that are not...

01 Jan 1970 12:00am GMT

Dominik Szopa: Announcing django-moderation

django-moderation is reusable application for Django framework, that allows to moderate any model objects.

Code can be found at http://github.com/dominno/django-moderation

Possible use cases:

Features:

Requirements

python >= 2.4

django >= 1.1

Installation

Download source code from http://github.com/dominno/django-moderation and run installation script:

$> python setup.py install

Configuration

  1. Add to your INSTALLED_APPS in your settings.py:

    moderation

  2. Run command manage.py syncdb

  3. Register Models with moderation

    from django.db import models
    import moderation
    
    
    class YourModel(models.Model):
        pass
    
    moderation.register(YourModel)
    
  4. Register admin class with your Model

    from django.contrib import admin
    from moderation.admin import ModerationAdmin
    
    
    class YourModelAdmin(ModerationAdmin):
        """Admin settings go here."""
    
    admin.site.register(YourModel, YourModelAdmin)
    

If you want to disable integration of moderation in admin, add admin_intergration_enabled = False to your admin class:

class YourModelAdmin(ModerationAdmin):
    admin_intergration_enabled = False

admin.site.register(YourModel, YourModelAdmin)

How django-moderation works

When you change existing object or create new one, it will not be publicly available until moderator approves it. It will be stored in ModeratedObject model.

your_model = YourModel(description='test')
your_model.save()

YourModel.objects.get(pk=your_model.pk)
Traceback (most recent call last):
DoesNotExist: YourModel matching query does not exist.

When you will approve object, then it will be publicly available.

your_model.moderated_object.approve(moderatated_by=user,
                                   reason='Reason for approve')

YourModel.objects.get(pk=1)
<YourModel: YourModel object>

You can access changed object by calling changed_object on moderated_object:

your_model.moderated_object.changed_object
<YourModel: YourModel object>

This is deserialized version of object that was changed.

Now when you will change an object, old version of it will be available publicly, new version will be saved in moderated_object

your_model.description = 'New description'
your_model.save()

your_model = YourModel.objects.get(pk=1)
your_model.__dict__
{'id': 1, 'description': 'test'}

your_model.moderated_object.changed_object.__dict__
{'id': 1, 'description': 'New description'}

your_model.moderated_object.approve(moderatated_by=user,
                                   reason='Reason for approve')

your_model = YourModel.objects.get(pk=1)
your_model.__dict__
{'id': 1, 'description': 'New description'}

Email notifications

By default when user change object that is under moderation, e-mail notification is send to moderator. It will inform him that object was changed and need to be moderated.

When moderator approves or reject object changes then e-mail notification is send to user that changed this object. It will inform user if his changes were accepted or rejected and inform him why it was rejected or approved.

How to overwrite email notification templates

E-mail notifications use following templates:

Default context:

content_type - content type object of moderated object

moderated_object - ModeratedObject instance

site - current Site instance

How to pass extra context to email notification templates

If you want to pass extra context to email notification methods you new need to create new class that subclass BaseModerationNotification class.

class CustomModerationNotification(BaseModerationNotification):
    def inform_moderator(self,
                     subject_template='moderation/notification_subject_moderator.txt',
                     message_template='moderation/notification_message_moderator.txt',
                     extra_context=None):
        '''Send notification to moderator'''
        extra_context={'test':'test'}
        super(CustomModerationNotification, self).inform_moderator(subject_template,
                                                                   message_template,
                                                                   extra_context)

    def inform_user(self, user,
                    subject_template='moderation/notification_subject_user.txt',
                    message_template='moderation/notification_message_user.txt',
                    extra_context=None)
        '''Send notification to user when object is approved or rejected'''
        extra_context={'test':'test'}
        super(CustomModerationNotification, self).inform_user(user,
                                                              subject_template,
                                                              message_template,
                                                              extra_context)

Next register it with moderation as notification_class:

moderation.register(YourModel, notification_class=CustomModerationNotification)

Signals

moderation.signals.pre_moderation - signal send before object is approved or rejected

Arguments sent with this signal:

sender - The model class.

instance - Instance of model class that is moderated

status - Moderation status, 0 - rejected, 1 - approved

moderation.signals.post_moderation - signal send after object is approved or rejected

Arguments sent with this signal:

sender - The model class.

instance - Instance of model class that is moderated

status - Moderation status, 0 - rejected, 1 - approved

Forms

When creating ModelForms for models that are under moderation use BaseModeratedObjectForm class as ModelForm class. Thanks to that form will initialized with data from changed_object.

from moderation.forms import BaseModeratedObjectForm


class ModeratedObjectForm(BaseModeratedObjectForm):

    class Meta:
        model = MyModel

Any comments ? Feedback ? Feature requests ?

01 Jan 1970 12:00am GMT

Caktus Consulting Group: Django and Hudson CI (Day 1)

We're always looking for new tools to make our development environment more robust here at Caktus. We write a lot of tests to ensure proper functionality as new features land and bug fixes are added to our projects. The next step is to integrate with a continuous integration system to automate the process and regularly [...]

01 Jan 1970 12:00am GMT

Caktus Consulting Group: Decoupled Django Apps and the Beauty of Generic Relations

Like just about everyone else, we've written our own suite of tools to help with building complex content management systems in Django here at Caktus. We reviewed a number of the existing CMSes out there, but in almost every case the navigation and page structure were so tightly coupled the system broke down when [...]

01 Jan 1970 12:00am GMT

Arne Brodowski: Einladung zur Django-UserGroup Hamburg am 23. März

Das nächste Treffen der Django-UserGroup Hamburg findet am Dienstag, den 23.03.2010 um 19:30 statt. Wie bei den letzten Malen treffen wir uns wieder in den Räumen der CoreMedia AG in der Ludwig-Erhard-Straße 18 in 20459 Hamburg (Anfahrtsbeschreibung auf Google Maps).

Bitte am Eingang bei CoreMedia AG klingeln, in den 3. Stock fahren und oben am Empfang nach der Django-UserGroup fragen.

Da wir in den Räumlichkeiten einen Beamer zur Verfügung haben hat jeder Teilnehmer die Möglichkeit einen kurzen Vortrag (Format: Lightning Talks oder etwas länger) zu halten. Die meisten Vorträge ergeben sich erfahrungsgemäß vor Ort.

Eingeladen ist wie immer jeder der Interesse hat sich mit anderen Djangonauten auszutauschen. Eine Anmeldung ist nicht erforderlich.

Weitere Informationen über die UserGroup gibt es in unserem Git Repository unter www.dughh.de und im Wiki des Deutschen Django-Vereins.

01 Jan 1970 12:00am GMT

Andriy Drozdyuk: Debugging production Django deployment

Deploying Django is a process that can drive one bananas. There are a lot of things to setup to go from your development environment to the production. Aside from the regular hassles - there come special little buggers that can really make you mad. If you ever had problems with 500.html pages, url configurations or import errors - you know what I mean.

However it doesn't all have to be that bad. There are quite a few steps you can take early on to minimize the pain. If you do get into trouble - there are some things you can do to debug out of it.


Preventative Measures

  1. Deploy early
    If you want to avoid the hassle of debugging 100 things at once, deploy your project as soon as possible. By "as soon as possible" I mean right after you create it - when there are no models, views and funky url settings!
  2. Commit often
    You are of course using source control for your project, correct? By committing often you allow for greater granularity of your project. In a way you "isolate" bugs in a particular commit. This makes finding them later on particularly easy.
  3. Deploy often
    Same as #1 - the only way to make sure it works - is to put it out into the wild!
  4. Separate production from development.
    You should have something like this in your settings.py file:
    if socket.gethostname() == 'server40.online.com':
    DEBUG = False
    else:
    DEBUG = True
    and feed all your other settings (i.e. database, media, etc) from this variable. This will make for painless deployment.
  5. Use dynamic path names
    Don't just hardcode "C:\Documents" or "/home/user/app" in your settings. Don't be lazy. This is how we do it:

    import os
    SITE_ROOT = os.path.dirname(os.path.realpath(__file__))

    and then go crazy for all the other path veriables:
    MEDIA_ROOT = os.path.join(SITE_ROOT, 'core/media')
    TEMPLATE_DIRS = ( os.path.join(SITE_ROOT, 'core/templates') )
    and so on...
  6. Checkout source code into production
    Don't just copy your code to production server with FTP or SCP! Install revision control like git or mercurial on the server, so you can hack away at the code without being afraid of messing things up, and more importantly - not loosing your important "tweaks" that you can only do in production.
Debugging the Deployed
  1. Check your path and full-qualify the import names
    Make sure you python path is correct. Sometimes the modules you can see in your development - are invisible in production.
    If your project structure is something like this:
    /project
    ---/app
    ------- views.py
    and you are importing your views in your urls.py files like so:
    from app import views
    than you might get a wierd handler500 error that makes no sense at all.
    Either reference your modules with full qualified names, i.e. "project.app.views" or put the path to your app directory into your path: "/home/user/blah/project/app".
  2. Back up - test - roll forward
    Sometimes you can't tell if the bug is from your latest update. Because production can keep some code in memory - one often fails to notice a bug until it is more than one update later.
    Your first order of business should be to find the bug exactly. Figure out which "commit" added that bug into the system.
    For this you must follow these steps:
    a) Roll back to some point in the code where it worked
    b) Restart your server, services etc... Make sure it works.
    c) Roll forward to the newer revision
    d) Restart. If everything still works - go to c).
    e) If stuff is broken Roll back to some point before a).
    Essentially you are doing a "binary" search on your commit history to isolate the bug. If you are using git - you can automate this process with git-bisect.
    Once you find the offending commit - roll your code to the revision before it, and start by copying by hand the code from the offending revisions.
    Hopefully because you kept your commits small, it should not be a lot!
  3. 90% it's urls and imports
    Most likely you screwed up your imports or urls. Check them over.
  4. The other 10% it's your 500.html and 404.html
    Did you create your 500.html and 404.html pages in your templates directory? The production environment won't work without them.
  5. User postgresql_psycopg2 and not postgresql
    This is more of a tip than debugging technique, but one often confuses the two. The new psycopg is termed psycopg2 and so we must use postgresql_psycopg2 for our database engine setting.
  6. Set DEBUG to True on production
    Just below your logic which determines your DEBUG variable, overwrite it temporarily with true.
    if blah..
    DEBUG = True
    else:
    DEBUG = False
    DEBUG = True # Overwrite temporarily

    This is a real hack, but it can temporarily give you some great insight into the problem.
Conclusion
In the end if you try to keep the "production" on your mind from the start, you deployment should be not a problem. Because one does not deploy very often, one tends to forget all the mistakes that were made previously. This makes it really challenging to get it "right" every time. Some time is spent going over the error logs and figuring out the same problems. However we cannot solve this. It will always be like so.
The best thing you can do is prepare for this process ahead of time - and once there, have effective ways of dealing with it.

01 Jan 1970 12:00am GMT