Best django questions in October 2011

Execute Python Script as Root (seteuid vs c-wrapper)

5 votes

I have a quick one off task in a python script that I'd like to call from Django (www user), that's going to need to root privileges.

At first I thought I would could use Python's os.seteuid() and set the setuid bit on the script, but then I realized that I would have to set the setuid bit on Python itself, which I assume is big no no. From what I can tell, this would also be the case if using sudo, which I really would like to avoid.

At this point, I'm considering just writing a C wrapper the uses seteuid and calls my python script as root, passing the necessary arguments to it.

Is this the correct thing to do or should I be looking at something else?

sudo does not require setuid bit on Python. You can enable sudo for one command only, no arguments:

 www          ALL=(ALL)       NOPASSWD:  /root/bin/reload-stuff.py ""

This would be secure if your script does not take any arguments, cannot be overridden by www user, and sudo does "env_reset" (the default in most distros).

You can accept arguments, but be very careful with them -- do not take output filenames, make sure you verify all inputs. In this case, remove "" from the end of sudo line.

Querying full name in Django

5 votes

How can I query on the full name in Django?

To clarify, I essentially want to do create a temporary column, combining first_name and last_name to give a fullname, then do a LIKE on that, like so:

select [fields] from Users where CONCAT(first_name, ' ', last_name) LIKE '%John Smith%";

The above query would return all users named John Smith. If possible I'd like to avoid using a raw SQL call.

The model I'm talking about specifically is the stock django.contrib.auth.models User model. Making changes to the model directly isn't a problem.

For example, if a user was to search for 'John Paul Smith', it should match users with a first name of 'John Paul' and last name 'Smith', as well as users with first name 'John' and last name 'Paul Smith'.

Unless I'm missing something, you can use python to query your DB like so:

from django.contrib.auth.models import User
x = User.objects.filter(first_name='John', last_name='Smith') 

Edit: To answer your question:

If you need to return 'John Paul Smith' when the user searches for 'John Smith' then you can use 'contains' which translates into a SQL LIKE. If you just need the capacity to store the name 'John Paul' put both names in the first_name column.

User.objects.filter(first_name__contains='John', last_name__contains='Smith') 

This translates to:

SELECT * FROM USERS
WHERE first_name LIKE'%John%' 
AND last_name LIKE'%Smith%'

Django+Postgres: "current transaction is aborted, commands ignored until end of transaction block"

5 votes

I've started working on a Django/Postgres site. Sometimes I work in manage.py shell, and accidentally do some DB action that results in an error. Then I am unable to do any database action at all, because for any database action I try to do, I get the error:

current transaction is aborted, commands ignored until end of transaction block

My current workaround is to restart the shell, but I should find a way to fix this without abandoning my shell session.

(I've read this and this, but they don't give actionable instructions on what to do from the shell.)

You can try this:

from django.db import connection
connection._rollback()

The more detailed discussion of this issue can be found here: https://code.djangoproject.com/ticket/10813

Django: Does unique_together imply db_index=True in the same way that ForeignKey does?

5 votes

A field on a model, foo = models.ForeignKey(Foo) will automatically add a database index for the column, in order to make look-ups faster. That's good and well, but Django's docs don't state whether the fields in a model-meta's unique_together receive the same treatment. I happen to have a model in which one char field which is listed in unique_together requires an index for quick lookups. I know that it won't hurt anything to add a duplicate db_index=True in the field definition, but I'm curious.

If unique_together does add an index, it will be a multiple column index.

If you want one of the columns to be indexed individually, I believe you need to specify db_index=True in the field definition.

Is PyCrypto safe and reliable to use?

5 votes

I am planning on using PyCrypto for a project and I want to know whether PyCrypto is safe and reliable enough to use. How can I ensure that PyCrypto is encrypting data correctly according to the various encryption algorithms such as RSA and AES?

Note that I am not an expert in crypto either. That said, I took a quick look at the PyCrypto code on github and at their mailing list. One of the things that gives me confidence is that there is good, expert contributions to the code base. The developers acknowledge insecurities and work to correct them.

If you have a specific use case that you need to be implemented securely, look at their code and ask on their list. Since they seem to leverage C/C++ libraries to do the work in many cases, you can check out the reputation of the base libraries directly.

Book for Django + Celery + RabbitMQ?

5 votes

OK, I have been reading about the celery and rabbitmq, while I appreciate the effort of the project and the documentation, I am still confused about a lot of things.

http://www.celeryproject.org/

http://ask.github.com/django-celery/

I am super confused about if celery is only for django or a standalone server, as the second link claims cerely is tightly used with django. Both sites show different ways of setting up and using celery, which to me is chaoic.

Enough rant, is there a proper book avaiable that I can buy?

Well not a book but I recently did setup in Dotcloud for Django+Celery, and here's the short doc: http://docs.dotcloud.com/tutorials/python/django-celery/

It's intended for simple tasks to be run asynchronously. There is a dotcloud-specific setup, but the rest might clear things up a bit. AFAIK, Celery started tightly coupled with Django but later became an entirely different animal, although it still retains superb compatibility with Django.

approximate search in a database

4 votes

I have a large database with a list of institutions (universities, hospitals, etc). The names of institutions come from different sources and can be spelled differently for the same institution. They can be misspelled, for example, or words can be shortened ("uni", or "univ", or "university")

Given a name that I need to insert in to the database, is there a practical way to find if this institution is already in the database? This is not a research project, so I am looking for a solution that is reasonably fast.

I am using django and postgresql, but it does not matter I suppose.

This is the problem of record linkage. Many databases provide basic methods for this such as character-level n-gram matching, where a term like "university" is expanded into

["uni", "niv", "ive", "ver", "ers", ...]

for n = 3. The database would index all such n-grams and allow a search with some kind of weighted matching. pg_trgm seems to do exactly this, try it out.

How to escape {{ or }} in django template?

4 votes

Django treats {{ var }} as some variable in its template. How can I escape {{ var }} or {{ or }} such that django does not treat it as variable.

<p>"{{ some text }}"</p> Should prints exactly the same.

I believe you are looking for the templatetag template tag.

As the linked-to doc states,

Since the template system has no concept of "escaping", to display one of the bits used in template tags, you must use the {% templatetag %} tag.

For example:

<p>"{% templatetag openvariable %} some text {% templatetag closevariable %}"</p>

will appear as so:

<p>"{{ some text }}"</p>

Deploying Django on an apache server

4 votes

OK, first off I am new to web development. So be gentle. AND thanks in advance. I am developing on windows env. and deploying on a linux server w/ Python 2.6.2 installed. Running apache2.2 as Virtual Host, and I am using mod_wsgi. I plan to serve media files from the same Virtual Host.

I have a django site and I am now ready to deploy. I am stuck, and every site I go to seems to be outdated/incomplete/overmyhead.

https://docs.djangoproject.com/en/1.3/howto/deployment/modwsgi/

http://www.djangobook.com/en/2.0/chapter12/

...only 2 links as for the newbness

The top link seems to be what I need yet I am still confused on these things:

  1. What does the file structure look like on the server
    • I cannot change/edit server files myself, I rely on the dba for that
    • I have django.wsgi, and django.wsgi~, where do those go?
    • Where do I put my project in relation to those wsgi files?

  2. The httpd.conf file is something that the server has on it? or do I create another?

  3. Do I need to put django in any way shape or form on the server? If so where? And what about the packages like registration, defaults?

Again sorry for the newbness, I have been banging my head for 2 weeks on this. Any help/links will be greatly appreciated unless they link me to the django-docs. I have read those...A LOT! thnx

Also go read:

http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango

and watch:

http://code.google.com/p/modwsgi/wiki/WhereToGetHelp?tm=6#Conference_Presentations

The latter includes Django examples and talks a bit about locations, permissions etc.

The first of these is even linked to in the document in the Django documentation.

Excluding South migrations from Pylint

4 votes

I'm using South for migration in my Django project. When I run Pylint on my project I get a bunch of errors from the migration files. How can I exclude migration files from Pylint?

I'm on a Windows system so I can't use filename exclusions in the Pylint options. I've tried to resort to adding # pylint: disable-msg-cat=WCREFI to the top of each of my migration files. It seems very kludgy and seems to be the last resort but this documented directive doesn't work and I get the error [E] Unrecognized file option 'disable-msg-cat'.

Any help?

Thanks

Adding the following to the .pylintrc file did it.

[MASTER]

# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
ignore=tests.py, urls.py, migrations

Blog excerpt in Django

4 votes

I am building a blog application in Django and when I display all the blogs I want to display a small blog excerpt with each entry. Can anybody tell me how can I do that?

One way to do that would be to make an extra field and store a fixed number of words for each blog entry, let's say 20 words. But then that would be storing redundant information in the database. Is there a better way to do that?

I suggest you use the truncatewords template filter.

Template example:

<ul>
{% for blogpost in blogposts %}
    <li><b>{{blogpost.title}}</b>: {{blogpost.content|truncatewords:10}}</li>
{% endfor %}
</ul>

If the blog content is stored as HTML, use truncatewords_html to ensure that open tags are closed after the truncation point (or combine with striptags to remove html tags).

If you want to truncate on characters (not words), you can use slice:

{{blogpost.content|slice:":10"}}

(outputs first 10 characters).

If content is stored as HTML, combine with striptags to avoid open tags problems: {{blogpost.content|striptags|slice:":10"}}

How to use SSL with Django app (deployed using mod_wsgi and virtualenv)

4 votes

Disclaimer: I don't really know what I'm doing, so I may have phrased things wrong. I've also never asked/answered a question on here before!

I have a Django app running on Apache that I deployed using mod_wsgi and virtualenv. I want some parts of the app to use SSL, however when I install the SSL certificate, the https URL goes to the index.html file from my public_html folder instead of the app (which is outside of public_html)

For example, visit https://tradekandi.com. That URL is just a basic HTML file: public_html/index.html Then visit http://tradekandi.com. That's my Django page (in maintenance mode).

I've searched stackoverflow and Google all day. I've tried removing the documentroot from the virtual hosts file but that did nothing. I tried adding a SetEnvIf X-Forwarded-Proto https HTTPS=1 line to it but that did nothing either.

My virtual hosts file has these lines in it:

SSLEngine on 
SSLCertificateFile /etc/ssl/certs/tradekandi.com.crt
SSLCertificateKeyFile /etc/ssl/private/tradekandi.com.key
SSLCACertificateFile /etc/ssl/certs/tradekandi.com.cabundle

Whenever I make any changes, I restart apache and "touch" the app's wsgi file.

How can I make the https URL load the Django app? Any help would be much appreciated. Thank you.

More of httpd configuration:

<VirtualHost 69.65.42.153:80>
ServerName tradekandi.com
ServerAlias www.tradekandi.com
DocumentRoot /home/trade/public_html
ServerAdmin webmaster@tradekandi.com
UseCanonicalName Off
CustomLog /usr/local/apache/domlogs/tradekandi.com combined
CustomLog /usr/local/apache/domlogs/tradekandi.com-bytes_log "%{%s}t %I .\n%{%s}t %O ."
## User trade # Needed for Cpanel::ApacheConf
<IfModule mod_suphp.c>
    suPHP_UserGroup trade trade
</IfModule>
<IfModule !mod_disable_suexec.c>
    SuexecUserGroup trade trade
</IfModule>
ScriptAlias /cgi-bin/ /home/trade/public_html/cgi-bin/

Include "/usr/local/apache/conf/userdata/*.conf"  
Include "/usr/local/apache/conf/userdata/*.owner-root" 
Include "/usr/local/apache/conf/userdata/std/*.conf" 
Include "/usr/local/apache/conf/userdata/std/*.owner-root" 
Include "/usr/local/apache/conf/userdata/std/2/*.conf" 
Include "/usr/local/apache/conf/userdata/std/2/*.owner-root" 
Include "/usr/local/apache/conf/userdata/std/2/trade/*.conf"  
Include "/usr/local/apache/conf/userdata/std/2/trade/tradekandi.com/*.conf"

</VirtualHost>

<VirtualHost 69.65.42.153:443>
ServerName tradekandi.com
ServerAlias www.tradekandi.com
DocumentRoot /home/trade/public_html
ServerAdmin webmaster@tradekandi.com
UseCanonicalName Off
CustomLog /usr/local/apache/domlogs/tradekandi.com combined
CustomLog /usr/local/apache/domlogs/tradekandi.com-bytes_log "%{%s}t %I .\n%{%s}t %O ."
## User nobody # Needed for Cpanel::ApacheConf
<IfModule mod_suphp.c>
    suPHP_UserGroup nobody nobody
</IfModule>
ScriptAlias /cgi-bin/ /home/trade/public_html/cgi-bin/
SSLEngine on

SSLCertificateFile /etc/ssl/certs/tradekandi.com.crt
SSLCertificateKeyFile /etc/ssl/private/tradekandi.com.key
SSLCACertificateFile /etc/ssl/certs/tradekandi.com.cabundle
CustomLog /usr/local/apache/domlogs/tradekandi.com-ssl_log combined
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
<Directory "/home/trade/public_html/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
Include "/usr/local/apache/conf/userdata/*.conf"
</VirtualHost>

If it's relevant, this is a dedicated server running CentOS & I am also using it to host one PHP-based site.

Wsgi file:

import os
import sys
sys.stdout = sys.stderr

from os.path import abspath, dirname, join
from site import addsitedir
sys.path.append('/home/trade/sites/tradekandi.com.env/lib/python2.7/site-packages')
sys.path.insert(0, abspath(join(dirname(__file__), "../../")))

from django.conf import settings
os.environ["DJANGO_SETTINGS_MODULE"] = "trade.settings"

sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

extra.conf with mod_wsgi directives:

Alias /static/ /home/trade/public_html/static/

<Directory /home/trade/public_html/static>
Order deny,allow
Allow from all
</Directory>

WSGIDaemonProcess trade python-path=/home/trade/sites/tradekandi.com.env/lib/python2.7/site-packages
WSGIProcessGroup trade

WSGIScriptAlias / /home/trade/sites/tradekandi.com.env/site/trade/deploy/pinax.wsgi

<Directory /home/trade/sites/tradekandi.com.env/site/trade/deploy>
Order deny,allow
Allow from all
</Directory>

Answering my own question for the benefit of anyone who may come across this:

I added the following lines:

WSGIProcessGroup tradek

WSGIScriptAlias / /home/trade/sites/tradekandi.com.env/site/trade/deploy/pinax.wsgi

to a .conf file located in /usr/local/apache/conf/userdata/ssl/2/trade/tradekandi.com, then used the command /scripts/ensure_vhost_includes --user=trade

(I also happened to change the ProcessGroup name)

Seems to have done the trick, although now I need to get rid of the insecure elements on the page! Thanks to Graham, because it was one of your answers to someone else that helped me figure this out.

Should I ensure that all my web application code is UTF-8?

4 votes

I have a Django site that contains only English language strings. I'll be localising this to other languages. I haven't set any sort of file encoding options. Do need to convert all my Python code to UTF-8? is this a good practice? If so, do I need to actually convert the file to be UTF-8 or do I simply need to add this snippet to each of my Python files # -*- coding: utf-8 -*-

Thanks.

The # coding: utf-8 line is only necessary for files which contain special characters directly. Depending on how you want to achieve l10n, you have to take care how you process the strings.

In Python2, you should use unicode() objects, while in Python3, normal str()ings are the thing to use.

Can you make a custom template tag that returns a queryset? If yes, how? - Django

4 votes

Let's make this very easy for my fellow SOians(?).

This is how normally the custom template tags work -

Template ->

{% block content %}

     blah blah blah

     {% custom_tag_load %}

{% endblock %}

The custom_tag_load is called and it returns a string. What I want to return is a queryset which I could possibly use like this ->

{% block content %}

     blah blah blah

     {% for x in custom_tag_load %}

          {{ x.datetime }}

     {% endfor %}

{% endblock %}

Note -> What I'm basically trying to do is to avoid passing the queryset through the view, and I'm not sure if I should be comfortable storing querysets in my global context.

You can return anything you like from a tag, including a queryset. However, you can't use a tag inside the for tag - you can only use a variable there (or a variable passed through a filter). What you could do is get your tag to put the queryset into a variable in the context, and use that variable in the for loop. See the docs on how to set a variable from a tag - although note that the development version has an easier method for doing this.

However, you shouldn't be concerned about putting a queryset into a context processor, either. Don't forget that querysets are lazy, so no database hit will be made unless the queryset is evaluated or iterated in the template.