Tag: django

Executing a lot of SQL queries with Django’s db API? Watch out for one thing.

I recently had the need to write an indexer that processes a lot of text files and creates a huge number of database rows (19 million+). This is a background script for an internal django website so I ended up using the standard django psycopg2 library, but tried to minimize the overhead by executing queries directly using the db cursor. Even after this consideration and special ‘del’ statements to clean things out after regular intervals, to my surprise, the process was still taking up a lot of memory. So, I tweeted about this experience. Daniele Varrazzo, one of the authors of psycopg2, tweeted back with more info.

Read full post...

code 400, message Bad request version

Lately I have noticed that I kept getting a 400 bad request when doing django development (i.e. using runserver) and browsing through Google Chrome. It was only Chrome that was behaving this way because Firefox would browse without generating any of these errors on the server side.

1
2
3
4
[09/Nov/2010 00:31:53] "GET /acq/ HTTP/1.1" 200 1393
[09/Nov/2010 00:31:53] code 400, message Bad request syntax ('\x16\x03\x00...')
?????????...." 400 -???8 .....?????
[09/Nov/2010 00:33:39] "GET /acq/ HTTP/1.1" 200 1393

I finally took a few minutes to debug. After clearing the cache and browsing data as suggested by many sites and having no luck I started disabling all of the extensions that I had installed. Guess what? The error disappeared.

This issue was being caused by the Secure Sites extension which lets you use secure versions of the site if one is available. In order to figure out whether a secure version is available it does an extra request, and it is this extra request that was causing the problem.

What’s the solution? I went into the options for this extension and added localhost to “Assumed no secure version exists” and the error disappeared.

Speeding up django’s development server on Windows

I am very picky about my development environment and I need it to be just right, otherwise the fun part of programming disappears. I have a dedicated Linux server in my office that is sharing and serving the development files. This is a solid server, fast enough that django’s development server refreshes as soon as I save the files, even before I have switched to my browser; and that’s how I like it! 🙂 Lately I have been on the road quite a bit so I have had to run the development environment on my tablet (when in Windows 7; runs excellent in Linux). The tablet has OK specs: 1.4GHz Core Duo with 2GB RAM and a 7200 RPM drive (generally the bottleneck). But for some reason django’s development server seems especially slow at serving the files. The refreshes after changes are OK, not fast, but OK. It is the media that it is very slow at serving (understandably so).

I did a lot of research on my options to speed this up. I am using the standard CPython distribution on Windows. I saw a lot of references to unladden-swallow, but there weren’t a lot of benchmarks to prove the speed gain yet. I realize that this is still under very heavy development, but the one benchmark that I found really excited me so I decided to give it a try. Unfortunately, after hunting for a number of source code packages necessary for compilation and still not succeeding I concluded that it wasn’t worth the time yet 😐 I decided to rule out pypy because of the possibility of compatibility issues, I wanted something that I could plug into the existing system. For some of my projects I am using external libraries, which might not work with pypy.

Anyways, my solution ended up involving Apache. Based on the console output of django’s dev server I had an idea that it was slow at serving multiple files. So I decided to serve the media, which generally is the majority of the files in a given view, using Apache and let django’s server deal only with the views. Microsoft’s IIS is also an option, but I had Apache setup for another project so I decided to use that. Below is a part of my dev_settings.py that makes this change.

1
2
3
4
5
6
7
8
9
import socket
# ...

# System specific dev settings.
if socket.gethostname() == "mystic":
	MEDIA_URL = 'https://thebitguru.com/projectname_media/'
	SERVE_STATIC_FILES = False
else:
	SERVE_STATIC_FILES = True

With this new combination and using 127.0.0.1 instead of localhost now my dev environment on Windows is fast enough to keep things interesting.

Migrating MySQL data to PostgreSQL

I just finished posting a new article about migrating a django application database from MySQL to PostgreSQL. This article is very technical and only covers the actual migration steps (i.e. does not explain why I made the move). Check it out if you are interested or curious.

Migrating MySQL data to PostgreSQL

Customizing the admin site listing for the standard Django User model

Django’s admin site is a great tool throughout development. Django also provides an authentication module that also reduces the development time. The problem is that the auth module predefines the admin classes that shows a very simplistic listing in the admin view.

By default this is how the admin view looks for the User model.

It is not easy to see how you can customize this. But if you read through django.contrib.admin.sites then the answers becomes clearer. You can unregister the existing class for the User model and register your own version. Below is what this translates to, put this code in one of your application’s admin.py (if you are calling admin.autodiscover in urls.py) or models.py files.

Read full post...

Setting up a development MySQL django user

Django creates a new test database every time you run the test cases, so I was wondering how I should setup the dev MySQL user so it can recreate the database without allowing this user to create or drop other databases.

Well, the answer was simple with MySQL since it doesn’t verify that the database exists before granting permissions on it. This resulted in the very convenient few statements below.

GRANT CREATE ON test_db_name.* TO dev_user@localhost;
GRANT ALL PRIVILEGES ON test_db_name.* TO dev_user@localhost;
FLUSH PRIVILEGES;

With these the dev_user can recreate this database as necessary. Have fun testing your applications 🙂

Django running slow on Windows?

I generally do my development on a dedicated development server running Linux with a fairly good amount of RAM (2GB) and a fast processor (the server does a lot more than just server django :)). Even when I am out of office I SSH to the development server. A few weeks ago I was on a trip where I wasn’t going to have good internet access for a lot of time. So, I decided to setup django on my tablet (Windows) to work locally. Everything was great until I had to access the site.

http://localhost:8000

waiting…

waiting…

Finally, after a few seconds the main page showed up. Then I clicked on a link.

waiting…

waiting…

Once again the page showed up after a few seconds. I was surprised how slow this was behaving. I booted to Linux and there it was very snappy. Unsatisfied with this performance issue, I did some searching and debugging and finally found out that the ‘localhost’ is what was causing the problem. As soon as I switched to the local IP address (127.0.0.1), the server came back to life!

If you are developing on Windows and the server seems to be a little slow then make sure to use ’127.0.0.1:8000’ instead of ‘localhost:8000’. If you are curious about the cause then search on google for complete explanation. Apparently this has to do with IPv6 and might a be non-IE issue.

Adding * to required fields

Django’s forms (previously knows as newforms) framework has a lot cool functionality including the ability to output label tags. So, instead of typing the complete label and setting the correct for, you can just do form.field_name.label_tag and everything else is taken care of for you. The only problem is that there is no easy, documented way of adding an indicator (e.g. *) for required fields. One way would be to do if’s on each field and manually add an asterisk in the template, but that’s not DRY. After some search a few weeks ago I found an interesting post by Adil Saleem that showed one way of easily accomplishing this without changing all of your templates.

I really liked Adil’s solution, but I also wanted to change the class on the label so I could make those fields stand out (through CSS), and I also realized that he was really creating a python decorator, but in a weird way. So, here is a revised version of his solution with a slightly different approach (overriding label_tag instead of __init__) that adds the required field indicator and specifies a special CSS class (“required”) through a python decorator.

First we define two functions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from django.utils.html import escape

def add_required_label_tag(original_function):
  """Adds the 'required' CSS class and an asterisks to required field labels."""
  def required_label_tag(self, contents=None, attrs=None):
    contents = contents or escape(self.label)
    if self.field.required:
      if not self.label.endswith(" *"):
        self.label += " *"
        contents += " *"
      attrs = {'class': 'required'}
    return original_function(self, contents, attrs)
  return required_label_tag

def decorate_bound_field():
  from django.forms.forms import BoundField
  BoundField.label_tag = add_required_label_tag(BoundField.label_tag)

The first function is a decorator that provides the functionality and the second function assigns this decorator to BoundField.label_tag. The second function is really a helper function that allows you to easily add this to all your form modules.

Add the above code to one of your library files (maybe project.forms.__init__.py) and then in the module that defines your forms add the following code.

1
2
from project.forms import decorate_bound_field
decorate_bound_field()

Other than this you need to define the “required” CSS class.

1
label.required { font-weight: bold; }

Refresh your page with the form and all of your required fields will have an asterisk and the labels will be bold. Credit goes to Adil Saleem for coming up with the initial version, this is just a refinement 🙂

FOWA is almost here!

FOWA

Future of Web Apps – Miami 09 is almost here. Both Jake Lumetta and I are planning on attending. In addition to the conference, we decided to attend the Miami barcamp on Sunday February 22nd. So, let me know if you will be at either of these events. You can also follow me on twitter (@farhanahmad).

After the cold temperatures that we have lately had (<30, generally around 20s) in Madison (WI) I am really looking forward to the warmer Miami weather (65! :))

gawk script for updating your models.py

Last evening I updated my django source to the latest SVN and found a surprise. The latest set of backwards incompatible changes were affecting my project. Specifically the new ModelAdmin moves were making things hard for me. Given that I have a few applications in django, I decided to write a script that would help speed up the process. What I ended up with was a simple gawk script that processes the models.py file and outputs the code for new ModelAdmin classes. I still have to manually remove the original admin classes because I didn’t want this to mess up things, but not having to look through the models and copy-pasting should save you some time.

For instance, if your models.py has three models-Tag, TaggedItem and NodeGroup-with Admin classes defined then this script will print out…

$ awk -f admin_model.awk models.py
class NodeGroupAdmin(admin.ModelAdmin):
                date_hierarchy = 'created_on'
                list_per_page = 25
                search_fields = ('title', )
                list_display_links = ('title',)
                list_display = ('id', 'title', 'created_on', 'updated_on', 'published', 'group_type',)
                list_filter = ('published','group_type',)
class TaggedItemAdmin(admin.ModelAdmin):
                pass
class TagAdmin(admin.ModelAdmin):
                pass
admin.site.register(Tag, TagAdmin)
admin.site.register(TaggedItem, TaggedItemAdmin)
admin.site.register(NodeGroup, NodeGroupAdmin)
$

I have added the usage instructions at the top of the script, and here is the script.