Django community: RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Django and mod_wsgi: A perfect match!
mod_wsgi is an Apache module for serving WSGI-based Python web applications from the Apache HTTP server. Django, along with almost every other Python web framework today, comes bundled with a backend for acting like a WSGI application. A couple of months ago I decided to try it out in spite of mod_python. Discovering and trying out mod_wsgi really suprised me. It can take a massive beating, and outperforms mod_python in every practical aspect. The setup You will need a short Python "bootstrap" script to create a WSGI-handler for your Django project. Here is an example (call it wsgi_handler.py and place it in the root directory of your Django project - the one with manage.py and settings.py): import sys import os sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..') os.environ['DJANGO_SETTINGS_MODULE'] = 'projectname.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() Finally set up your Apache virtualhost to use mod_wsgi: <VirtualHost *> ServerName www.projectname.org ServerAlias *projectname.org Alias /admin_media /usr/lib/python2.4/site-packages/django/contrib/admin/media <Location /admin_media> Order allow,deny Allow from all </Location> Alias /media /home/user/projectname/media <Location /media> Order allow,deny Allow from all </Location> WSGIScriptAlias / /home/user/projectname/wsgi_handler.py WSGIDaemonProcess projectname user=user group=user processes=1 threads=10 WSGIProcessGroup projectname </VirtualHost> In the WSGIDaemonProcess line, you can easily manage the amount of system resources (measured in processes and threads) mod_wsgi should … -
Building a website API with Django. Part 5: Serialization
Let me start this entry announcing the first beta releases of wapi-0.2 and django-oauthsp-0.2. Keep in mind this code is released under AGPLv3, as per the reasons detailed in this entry. Note also that the API is subject to change before reaching 0.2, this code should be considered as a preview release. Now let's talk about <serializations />! Principles Wapi serializers, as opposed to the Django serializers, let you fully customize how an object is serialized. You can even specify multiple ways of serializing an object, depending on multiple things. However, this flexibility comes with a price: complexity. Declaring serializers in Wapi is not an easy task. So let's start explaining the basics. Class based approach (again) Serializations are specified as a class, which inherits from wapi.serializers.Serializer, defining multiple methods which return a dictionary. Every method is a serialization "preset", which you can specify at the time you serialize the objects. Let's see a brief example: from wapi.serializers import Serializer from wapi import serializers from notes.models import UserProfile class UserProfileSerializer(Serializer): serializes = UserProfile @serializers.objname('user') def default(self, obj, **kwargs): return { 'username': obj.user.username, 'display_name': obj.display_name, 'avatar32': obj.get_avatar_url(32), 'avatar128': obj.get_avatar_url(128), } As you see, we've defined a class with the serializes attribute. … -
Why I choose AGPLv3 for my code
From now, all the code for Django applications I'll be releasing will be under AGPLv3, which means every application using them will need to be under the same license (which requires your code to be available). You may be thinking why I'm doing this, so I'll give you an explanation. I've recently spotted some freeloaders in the Django community, and that's something I usually don't like. I understand that making your code available doesn't always makes sense, because sometimes your application is too vertical and the only ones benefiting from your code are the ones who are competing with you. But if you write something which could potentially benefit hundreds of sites which don't compete with you and you choose to make it closed source, then you're not going to get my code for free. Keep in mind that I'm not preventing you from building commercial products with my code, as long as you release your work under AGPLv3. I don't have any problems with people making money off my work, as long as they give something back. However, as I mentioned, sometimes I can understand your situation. If you want to use this code to build a non-AGPLv3 product, … -
Cited in Bangalore - How cool is that?
As Pradeep just pointed out in my Blog comments, he used parts of my posting on video blogging with Django (which is funnily enough always referenced as “Create your own YouTube site” - a claim I wouldn’t have dared make myself ) as basis/inspiration for a presentation at Bar Camp Bangalore. BarCamp describes [...] -
Amazed at Django
I spent this weekend working on a new portal site for which I had the idea a couple of days ago (yeah, I know — weekends are for something else; but it was absolutely freezing cold here in Germany, so I succumbed to my inner geek). I’m building the site using the Python Web framework [...] -
New travel portal opened: trogger.de
German-language travel site trogger.de opens. -
Django book completed. Congrats to Adrian and Jacob!
Jacob Kaplan-Moss posted to his blog yesterday that the Django book (Pro Django. Web Development Done Right) is completed and is now going off to the printers. He writes: “It should start shipping to bookstores around the second week of December.”This is great news! It’s great news for the Django platform — it’s a true [...] -
Inspiration for a RentaCoder listing
An interesting (well, to me anyway) tangent to my recent post about GetAFreelancer. While looking through my Google Analytics report, I just found a number of referrals from rentacoder.com. Looking further, I find that someone had been looking for a developer for build a solution for “Video Blogging using Django and Flash(tm) Video (FLV)”.If this [...] -
New Django installation
I just got a new machine, with x64 processor (Pentium D Dual Core — nice machine!) and naturally it’s already running Linux. SUSE 10, to be specific. Now I wanted to move my Django project over from the old machine and the Django installation kept failing. The setup.py told me: Installed /home/tietze/temp/Django-0.91 Because this distribution was installed [...] -
English version of trogger travel portal launched!
I just launched the English language version of my Django-powered travel portal, trogger.de. The newly-launched English version is at trogger.info. For those who haven’t yet checked out trogger, trogger is a travel-oriented Web community site, where users can maintain travel blogs, post travel reports, share holiday insider tips and publish photo albums. The most recent extension [...] -
Video Blogging using Django and Flash(tm) Video (FLV)
I just added Flash-based (FLV) video blogging support to my Django-powered travel portal site, trogger.de. The whole process is surprisingly simple and straightforward and can be done entirely with free (FLOSS) tools. The video publishing workflow consists of the following parts: A Django model to store our video and associated information An upload form where the user can [...] -
Extending the Django User model with inheritance
Update March 2013: Django 1.5 includes a configurable custom user model that makes all this obsolete. Extra fields for Users Most of the Django projects I’ve worked on need to store information about each user in addition to the standard name and email address held by the contrib.auth.models.User model. The old way: User Profiles The solution in the past was to create a “user profile” model which is associated 1-to-1 with the user. Something like: the model class UserProfile(models.Model): user = models.ForeignKey(User, unique=True, related_name='profile') timezone = models.CharField(max_length=50, default='Europe/London') config in settings.py AUTH_PROFILE_MODULE = 'accounts.UserProfile' usage profile = request.user.get_profile() print profile.timezone It works ok, but it’s an extra database query for each request that uses the profile (it’s cached during the request so each call to get_profile() is not a query). Also, the information about the user is stored in two separate models, so you need to display and update fields from both the User and the UserProfile models. The new way: Model Inheritance As part of the great work done on the queryset-refactor by Malcolm et al, Django now has model inheritance. If you’re using trunk as of revision 7477 (26th April 2008), your model classes can inherit from an … -
Decorating the Render Methods of New-Form Widgets
Perhaps all template masters have already faced the problem of styling HTML input fields of different types. The selectors like input[type=checkbox] and similar in CSS are not supported by IE so people working with templates and CSS obviously need some other way to select and style specific types of input fields.There are a few ugly ways to do that which violate the DRY principle:Encompassing the form element in the template with HTML tag which has a class representing specific type of the input field.For example:<span class="form_checkbox"> {{ form.is_privacy_policy_confirmed }}</span>Defining the specific CSS class for each form field widget in the form.For example:class FormExample(forms.Form): is_privacy_policy_confirmed = forms.BooleanField( required=True, widget=CheckboxInput(attrs={'class': 'form_checkbox'}), )Extending all Fields and all Widgets which use HTML input fields and using the extended versions instead of the originals. I don't like any of them, because they force me or the template formatters to repeat ourselves and make plenty of replacements in our existing forms.Although "most sane developers consider it a bad idea", I see the Guerrilla patching of the Widget's render method as the nicest solution to solve this problem.Guerrilla patch is the modification of the runtime code in dynamic languages without changing the original source code.The method render … -
Fret Free -- Introduction to Django and the Django Software Foundation
LinuxPro Magazine just released my latest article, an introduction to Django and some discussion about the newly created Django Software Foundation. Being a life long Perl user, I didn't think I would enjoy Django at all. I have to admit that it is a VERY polished system. It has great PostgreSQL support, in fact the core developers smartly prefer it over MySQL for their own systems. You can download a PDF copy of the article at, Fret Free -- Django and the Django Software Foundation. The print issue will hit the stands in October. Hope you enjoy it! -
PyCon Rio: e lá vou eu...
Confirmado: estou indo para a PyConBrasil, edição Rio de Janeiro. O evento ocorrerá durante os dias 18, 19 e 20 de setembro. Estarei por lá nos dias 17 à 21. Quem vai? Será que galera da Django Brasil estará em peso por lá para um encontro informal!? Maiores informações, no site do evento: http://pyconbrasil.com.br/. -
StaticGenerator for Django Updated (1.3.3)
As reported by Matt Dennewitz, Django changed the request attribute path to path_info in rev 8015. StaticGenerator has been updated to reflect the change. -
Building a website API with Django. Part 4: Complex functions
We've talked about how the API functions are defined in WAPI, but we've only scratched the surface. This entry will go on details about function namespacing, optional parameters, parameter sets, parameter validation and allowed request methods, showing some real examples from the code I wrote for byNotes. Namespacing your functions As we've seen in the first post in this series, you API is loaded at an URL, for example http://example.com/api/1.0/rest/, so if you define a function named foo, it will be accessible from http://example.com/api/1.0/rest/foo.xml (or json or yaml). This is enough if your API consists only of a few functions. But what happens when your API has 50 functions? WAPI provides support for namespacing your API. You only need to prepend your method with your namespace name and the binding will take care of splitting them. For example, the ReST binding uses the pattern namespace/function_name, while the upcoming XML-RPC binding will use namespace.function_name. Let's see an example: class BynotesApi(object): ... @required_parameter('id', int, _('The geoname id you want to retrieve information for.')) def geo__hierarchy(self, request, dct): """Returns the hierarchy for the given geoname id, starting from itself.""" try: geoname = Geoname.objects.get(pk=dct['id']) except Geoname.DoesNotExist: return SingleSerializableResponse(None) return SerializableResponse([geoname] + geoname.hierarchy) As you … -
Celebrity Fantasy Game in Django
If you've played fantasy football or any fantasy sport you know what I'm takling about. If you're new to the concept, you pick a roster of celebrities and if they show up in the news, you get points. The site was written using Django (trunk as of the 13th!) and Postgres 8.2. We've built a fantasy games package on top of the Django core which we would probably open-source if the community showed some interest in it. This is our 2nd major site in Django and we really love it. To begin with, Python is a great language. When we built our fantasy engine, it was originally coded on MySQL. We encountered quite a few problems porting it over to Postgres. There are lots of little things where MySQL does type conversions for you automatically and Postgres (correctly in my opinion) does not. I definitely feel the conversion was worth it so that now we're on an enterprise level database. A side project that matured during this project is a multi-threaded mail delivery engine. It comes with some handy functions to send fully HTML/txt encoded emails with images embedded and all. I'll create a snippet for that mail engine in … -
Building a website API with Django. Part 3: OAuth in Django
I've received some emails asking for the WAPI code, so I'll start addressing that point. The code I'm including in this series doesn't work with the latest releases of WAPI and django-oauthsp, so you'll have to wait until I prepare the new releases. I'm just holding them until I finish writing this post series because, while writing about these APIs, I'm still adding new features, fixing some bugs and making the syntax nicer. I still have to write three more posts (complex functions, serializations and documentation), so you can expect a release around the end of this month. I'll write an entry announcing it. I had initially planned to include all the remaining information for API authentication in this post, but since I have to explain how you can integrate django-oauthsp into your projects, it turned to be so long. HTTP Basic authentication has been already covered, so the only missing bit regarding authentication would be HTTP Digest using the digest application. I'll explain it in one of the remaing posts in this series that turns to be shorter than expected. OAuth protocol implementation in django-oauthsp django-oauthsp implements the OAuth Core 1.0 protocol plus four extensions. Two of them are … -
Django: Inserting and Positioning Images
A few days ago I stumbled upon a thread over at the Django users mailing list discussing how to handle media in Django. It raised the interesting question of how do you associate images and files with your articles, blog posts, etc. When I started this blog I — too — realized I needed a way to insert and position images in my blog posts. Django only gives you a way to store text and images and leaves the rest up to us, the users of Django. My solution uses Markdown as the markup language. All my post are written and stored in the database as Markdown. Markdown might be too low-level for end users or non technical editors. It is more than user-friendly enough for me, but your milage may vary on this depending who’s creating the content on your site. One of the nice things about Markdown is that it has a very handy syntax for inserting images without having to type any HTML: 1 2![Alt text][id] [id]: url/to/image "Optional title attribute" Running the above through Markdown will convert it into a nice <img> tag. However, I would have to manually figure out and insert the path to all my images, … -
Cross-domain Session Cookie for Multiple Domain
Django provides for cross-domain session cookie settings. By default your session cookie is only set for your subdomain (example.com or blog.example.com). What django's cross-domain cookie settings does, however, is set it for all sub-domains. That is if your user enters your site from example.com, your session's cookie will be set as '.example.com' which in turn make it available to all sub-domains: foo.example.comHere is the docs for this settings:# Default: None # The domain to use for session cookies. Set this to a string# such as ".lawrence.com" for cross-domain cookies, or use None# for a standard domain cookie. See the session docs.SESSION_COOKIE_DOMAIN = '.lawrence.com'The problem with this settings comes in when you intend to have your django setup serve multiple domains. That is, this setting will explicitly set the cookie's domain as '.lawrence.com' which in turn prevents the any other domain to obtain a cookie pointing to this django setup.Out there to see how I can address this issue, I changed the behavior of this setting to also allow for automatic insertion of whatever host as such:SESSION_COOKIE_DOMAIN = '.%(host)s'the above settings works as well as the old behavior:SESSION_COOKIE_DOMAIN = '.lawrence.com'Click here to download the patch and replace it with your:/django/contrib/sessions/middleware.py -
Adding search to a Django site in a snap
Search is a feature that is – or at least, should be – present on most sites containing dynamic or large content. There are a few projects around to tackle that. Here’s a non-exhaustive list: djangosearch, django-search (with a dash), django-sphinx. Those search engines are great, but they seem like overkill if you just need a simple search feature for your CMS or blog. To deal with that, I’ve come up with a generic and simple trick. All you need is copy/paste the following snippet anywhere in your project: import re from django.db.models import Q def normalize_query(query_string, findterms=re.compile(r'"([^"]+)"|(\S+)').findall, normspace=re.compile(r'\s{2,}').sub): ''' Splits the query string in invidual keywords, getting rid of unecessary spaces and grouping quoted words together. Example: >>> normalize_query(' some random words "with quotes " and spaces') ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] ''' return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)] def get_query(query_string, search_fields): ''' Returns a query, that is a combination of Q objects. That combination aims to search keywords within a model by testing the given search fields. ''' query = None # Query to search for every search term terms = normalize_query(query_string) for term in terms: or_query = None # Query to … -
Postback: Horror story with GeoDjango
Instead of replying to the comments, I decided to write a postback, since there are a few points I want to address. As John De Rosa guessed, I expecteded to receive some flamage because I've been in both sides situations like this before and I know it works. I've been the flamer and the flamed, but everytime the discussed issue ended up solved much anticipately that expected. We (people involved in FOSS) don't like flames, so when people start flaming, we look at the issue much quicker. That's how it works. Remember the Linus vs. Gnome flame? As D (BTW, it would be nice if people posted with their real names) pointed, I'm possibly using the wrong approach for the distance queries. But the truth is I didn't come with that ORM call myself. I got it from the GeoDjango documentation. So we have another problem here: the documentation has wrong examples. If you put something in the examples, don't yell when people tell you it doesn't work, And finally, as M pointed, I haven't got in touch with the GeoDjango developers. But that's because I have nothing useful to report. Shoud I report a bug telling: "Hey, I loaded … -
Horror story with GeoDjango
Last week I ported my geonames application to GeoDjango and I've ended up reverting all the changes and turning back to custom SQL. First, let me tell you what the geonames database is about. It contains almost 7 million geographical places and you can download the full dump under a Creative Commons BY-SA license. The first problem I encountered was importing the dataset. Since I need to do additional processing in their database dumps, I can't simply COPY the files to the database. When GeoDjango didn't exist, I decided to write a python script using the DB API and insert all the records that way. It worked fine, but it wasn't portable between different databases. So, when porting django-geonames to GeoDjango, I started by modifying the import script to use the Django ORM. First fail!. The script started running (with settings.DEBUG = False) and two hours later (importing the data with the Python script took around 1 hour) the OOM started killing processes. Well, I decided to left the script as it was before, but port the models and the custom SQL calls to the GeoDjango ORM. And I modified the models, adding some spatial fields and then removed all … -
Building a website API with Django. Part 2a: API authentication
As Gregor Müllegger suggested, I'm now writing about API authentication. This article talks only about user authentication methods without external dependencies, while methods which require other applications have been left for the next article. I was going to include them all in one article, but since I would also need to explain how django-digest and django-oauthsp work, this article would be too long. How authentication works in WAPI Authentication in WAPI works by using a middleware layer. WAPI ships with authentication middleware for HTTP Basic, HTTP Digest and OAuth. You'll usually need to subclass one of the provided middlewares, since the authentication realm is part of the class. When you plug a WAPI binding you can choose to add an authentication middleware class to it. Adding multiple authentication classes at the same API url is not supported, since different authentication methods return different WWW-Authenticate. However, you can support multiple authentication methods by using multiple API urls. For example, let's see my urls.py at byNotes: # urls.py from notes.api import BynotesApi, ApiAuthOAuth, ApiAuthBasic ... (r'^api/1.0/rest/oauth/%s$' % RestBinding.PATTERN, RestBinding(auth=ApiAuthOAuth(), api=BynotesApi())), (r'^api/1.0/rest/basic/%s$' % RestBinding.PATTERN, RestBinding(auth=ApiAuthBasic(), api=BynotesApi())), Requesting user authentication WAPI comes with a login_required decorator, which is not the same decorator provided by …