The 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:
- One to create 10/100/500/1000 instances of my class
- One to edit one field of all 10/100/500/1000 instances
- One to delete each of the 10/100/500/1000 instances
01 Jan 1970 12:00am GMT
Peter Bengtsson: How and why to use django-mongokit (aka. Django to MongoDB)
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.
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:
- User creates his profile, profile is not visible on site. It will be visible on site when moderator approves it.
- User change his profile, old profile data is visible on site. New data will be visible on site when moderator approves it.
Features:
- configurable admin integration(data changed in admin can be visible on site when moderator approves it)
- moderation queue in admin
- html differences of changes between versions of objects
- configurable email notifications
- custom model form that allows to edit changed data of object
- 100% PEP8 correct code
- test coverage > 80%
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
-
Add to your INSTALLED_APPS in your settings.py:
moderation -
Run command
manage.py syncdb -
Register Models with moderation
from django.db import models import moderation class YourModel(models.Model): pass moderation.register(YourModel)
-
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:
- moderation/notification_subject_moderator.txt
- moderation/notification_message_moderator.txt
- moderation/notification_subject_user.txt
- moderation/notification_message_user.txt
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
- 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! - 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. - Deploy often
Same as #1 - the only way to make sure it works - is to put it out into the wild! - 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. - 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... - 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.
- 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". - 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! - 90% it's urls and imports
Most likely you screwed up your imports or urls. Check them over. - 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. - 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. - 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.
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