Posts for the 'django' Category

  1. Django settings in template

    So what do you do if you require a django setting in your templates, much like we have MEDIA_URL today?

    Well there are use cases for this, (if you are in doubt have a look at the original ticket for adding MEDIA_URL to django ).

    The easiest way that I have found so far is to write a context processor. For example in my settings I might have JAVASCRIPT_URL (which in my real life code changes depending on whether I am running in debug, test or from a CDN):

    JAVASCRIPT_URL = 'http://myjshost.com'

    Now from here I would like to make this available in my templates. Create a new python file that is somewhere on your python path (Under my project, I create a utils directory and then put a file context_processors.py in there. Don’t forget __init__.py should live in that directory as well).

    In the context_processors.py file simply put


    def javascript_url(request):
    from django.conf import settings
    return {'JAVASCRIPT_URL': settings.JAVASCRIPT_URL}

    In your settings.py file you might already have a reference to TEMPLATE_CONTEXT_PROCESSORS if not then add it like so:


    from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
    TEMPLATE_CONTEXT_PROCESSORS += (
    'django.core.context_processors.request',
    'django.core.context_processors.i18n',
    'appname.utils.context_processors.javascript_url',
    )

    And thats about it. From there on in you will be able to use JAVASCRIPT_URL like MEDIA_URL:

    {{ JAVASCRIPT_URL }}

    By timc3 on the
    January 22nd, 2010
  2. Leading zeros in django

    I am always forgetting about the stringformatting tag in Django’s templating language. For instance for leading zeros:


    {{ variable|stringformat:"02d" }}

    This will always put a leading zero.

    By timc3 on the
    July 13th, 2009
  3. Django test fixtures and contenttypes

    Just came across an interesting problem with the contenttypes contributed application and the test framework.

    If you are using fixtures in the test frame work you might find that the database gets out of date as you are working on it, particularly if you are creating new models all the time.

    To get around this you need to regenerate the contenttypes database. If you depend on this, the following steps could give you problems so make sure that you back up your data (dumpdata) beforehand.

    So first off drop the database:

    [cc lang="bash]python manage.py reset contenttypes[/cc]

    If the database has foreign key dependancies on contenttypes you will not be able to reset it like that. Use a database administration tool and drop cascade on the django_content_type table instead.

    Then sync the database to create a new contenttypes table:

    [cc lang="bash]python manage.py syncdb[/cc]

    Now you are ready to dumpdata into a fixture:

    [cc lang="bash]python manage.py dumpdata contenttypes > fixtures/testdata.json[/cc]

    By timc3 on the
    May 29th, 2009
  4. django one form, two models

    This post is a work in progress is now working I am glad to say. I have been working on a django site which needs two models updated for one post. It is actually using models very close to that on django-forums and I have created a forms.py file:


    class ThreadForm(forms.ModelForm):
    class Meta:
    model = Thread
    exclude = ('forum', 'sticky', 'closed', 'posts', 'views', 'latest_post_time')

    def clean_title(self):
    title = self.cleaned_data['title']
    if not alnum_re.search(title):
    raise forms.ValidationError(ugettext("Titles can only contain letters, numbers and underscores"))

    if len(title) < 1:
    raise forms.ValidationError(ugettext("Please enter a title"))
    return title

    class PostForm(forms.ModelForm):
    class Meta:
    model = Post
    exclude = ('thread', 'author', 'time', 'related_item')

    def clean_body(self):
    body = self.cleaned_data['body']
    if len(body) < 1:
    raise forms.ValidationError(ugettext("Please enter some body text"))
    return body

    And then in my views (after importing in the correct models):

    @login_required
    def groupnewthread(request, slug):
    thegroup = get_object_or_404(GroupsOfUser, slug=slug)
    if request.method == 'POST':
    f = request.POST.copy()
    tdata = {
    'title': f['title'],
    }
    pdata = {
    'body': f['body'],
    }
    t = ThreadForm(tdata)
    p = PostForm(pdata)
    if t.is_valid():
    newthread = t.save(commit=False)
    newthread.forum = thegroup

    if p.is_valid():
    newthread.save()
    newpost = p.save(commit=False)
    newpost.thread = newthread
    newpost.author = request.user
    newpost.save()

    strmessage = 'has created a thread %s' % (newthread.get_absolute_url(), newthread.title)
    usm = UserStatus(user = newpost.author, message = strmessage)
    usm.save()

    return HttpResponseRedirect(reverse('groupdetail', args=[thegroup.slug]))

    else:

    t = ThreadForm()
    p = PostForm()

    objContext = RequestContext(request, {'threadform': t, 'postform': p})
    return render_to_response('groups/group_thread_add.html', objContext)

    Now the bit that is in progress is the returning part of dealing with the form data being bound, but I am going to write a custom handler. This is obviously going to be much easier to handle than an update, which I will have to deal with at a point.

    The form HTML looks like this btw:


    {% extends "base.html" %}
    {% load i18n %}
    {% block title %}
    {% trans 'Add a new group thread' %}
    {% endblock %}
    {% block body %}

    {% trans 'Create a new group thread' %}

    {% if t.errors %}

    {% blocktrans count t.errors|length as count %}Please correct the following error:{% plural %}Please correct the following errors:{% endblocktrans %}

    {% endif %}
    {% if p.errors %}

    {% blocktrans count p.errors|length as count %}Please correct the following error:{% plural %}Please correct the following errors:{% endblocktrans %}

    {% endif %}

    {{ threadform.as_table }}
    {{ postform.as_table }}

    {% endblock %}

    By timc3 on the
    June 21st, 2008
  5. Looks like Django is really taking off

    Since the introduction of Google’s appengine which includes support for some of Django’s code, and the template system there has been an incredible amount of press for Django.

    At the moment there is no backend support for AppEngine in Django (and DB2 support is still lacking – there was a blog post about a year ago but nothing seems to have happened since, and I would love to be proved wrong on that one) but it must only be a matter of time before this happens so for the moment you have to disable the ORM support. Pity, but I can see why.

    But I am glad that Django is getting the attention that it deserves, I have long know that Python is well used in Google (and Yahoo for that matter), and now we should see even more people using Django which can only be a good thing for the ever-growing community.

    Here is an excellent write-up on Google App Engine http://www.dougma.com/archives/81

    By timc3 on the
    April 18th, 2008
  6. Django and URLS naming

    Django URLs naming can be a pain sometimes, unless it is just me but an easy way to debug is to use Django’s shell and import urlresolvers:

    python manage.py shell

    >> from django.core.urlresolvers import reverse
    >> reverse('nameofurl')

    If there are arguments in the URLS field (for instance passing in the slug):


    >> reverse('nameofurl', 'slug') [/sourcecode]

    Then it should resolve the name to the URL path needed. If it doesn’t, well something is wrong. We got a weird Traceback when using Python 2.5 though:


    Traceback (most recent call last):
    File "", line 1, in
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 297, in reverse
    return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs))
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 282, in reverse
    if lookup_view in self.reverse_dict:
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 221, in _get_reverse_dict
    self._reverse_dict[pattern.callback] = (pattern,)
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 178, in _get_callback
    self._callback = get_callable(self._callback_str)
    File "/Users/azimi/Code/Python/Django/django-trunk/django/utils/functional.py", line 130, in wrapper
    result = func(*args)
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 47, in get_callable
    lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
    File "/website/xmlrpc.py", line 8, in

    dispatcher = SimpleXMLRPCDispatcher() # Python 2.4
    TypeError: __init__() takes exactly 3 arguments (1 given)
    >>> reverse('homepage')
    Traceback (most recent call last):
    File "", line 1, in
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 297, in reverse
    return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs))
    File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 284, in reverse
    raise NoReverseMatch
    NoReverseMatch

    Looks like something is broken in support for python 2.5 on OS X with django, but I wonder if it is just us thats found this.

    By timc3 on the
    March 13th, 2008
  7. Django and OSX

    Those who have been here before know that I am a big fan of the Django python webframework, and also a big fan of OS X. So I thought that I would install Django on my MacBook Pro.

    I did have it all installed on my G4 laptop, but I am going to be using it with at least two different databases on this machine. I am not going to give a complete, what I typed style install, just an overview because it is fairly easy.

    1. Install latest version 2.4.* of Python from http://www.pythonmac.org
    2. Check out the development version of Django from http://www.djangoproject.com/download/ (I checked it out in /django – probably not the best place to put it.)
    3. Install latest stable version (5.1) of MySQL from http://www.mysql.com/
    4. Install latest stable version of MySQL tools http://www.mysql.com/products/tools/administrator/
    5. Install MySQLdb from http://www.pythonmac.org/packages/py24-fat/index.html
    6. Create a symlink so Python can find django: ln -s /django/django_src/django/ /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django
    7. Then I followed some instructions on blog.vixiom.com to add the path that I need.
    8. edit your .bash_profile file in your home directory with the following path: /django/django_src/django/bin/:/Library/Frameworks/Python.framework/Versions/Current/bin:

    Now that should be everything needed to start running with Django and MySQL. PostGreSQL is of course the better database but for the testing work that I am doing my webhost at the moment doesn’t support PostgreSQL..

    By timc3 on the
    July 9th, 2007
  8. Django site comments and all!

    I haven’t been posted that much here recently and thats because I have been doing other things and working on other sites. I have also built a new server for home, which will be detailed later, but first and foremost I am still playing with Django and build a site using it.

    I have had enough with doing WordPress sites, and although I do know it fairly well I wanted to write something a bit more tailored to the application. And its a good test for the plans I have for other applications later on.

    Django I am enjoying, but its not with out frustration. And although in parts it is amazingly well documented for a framework thats been in the public eye for a relatively shorttime it does miss out on the docs in some parts. I am finding that some things are overdocumented and its hard to find relatively simple bits of information and others such as the comment system just isn’t documented.

    Although they are quite upfront about the comment system needing documents, it is an area that slows down the production pipeline quite alot, to the point where its as slow going as any other development. I suppose I can’t complain too much but still I hope this gets addressed reasonably quickly. I should put down my own experiences with the comment system at this point for others to use, but it should be noted that I don’t know much at all and this is only my findings and what I have so far:

    1. The Django comment system is broken up into three areas – Comments, Karma and Freecomment and if you are interested in what these contain then looking at the database should be your first port of call.
    2. Free comments and comments are different though in some cases if you are using a template or method using free_ then you can sometimes safely omit free_ and get the standard comment system.
    3. The standard comment system is based around logged on users, while freecomments seems to be open to all.
    4. At the moment due to the lack of documentation the two best places to find out information is from the django source itself /django/contrib/comments and in the sourcecode posted by Jeff Croft for his Lost-Theories website.

    Here you can see the django comments tables in MySQL (my host doesn’t yet support PostGreSQL, so I develop in the same database I am going to host on).

    MySQL view of the comments system

    So this has lead me to get a working but rough comments module into my test site. I am using a mixture of my own views and generics like most, and I have created my own templates for the tables in my model.

    In the details page for one model, I am pulling out some information from the post like so:

    {% block content %}
    {{ object.article_body|escape|linebreaks }}
    {% endblock %}

    Then I am referring to the comments. My model is called Post so that is what I am pulling the comments out for:

    {% block metacontent %}
    {% load comments.comments %}
    {% get_comment_list for website.post object.id as comment_list %}
    {% ifequal post.get_comment_count 0 %}
    No one has posted any comments yet. Perhaps you'd like to be the first?
    {% endifequal %}
    {% for comment in comment_list %}
    {{ comment.comment }}
    {% endfor %}

    Then I pull in the standard comment form:

    {% comment_form for website.post object.id%}

    In your templates directory you can then create a subdirectory called “comments” and the commenting system will search in here first for the comments templates before using its own.

    I copied the form.html template in here and modified it, and then I also created templates for posted.html and preview.html. If you are looking for ideas for these two again Jeff Croft’s source code for Lost-Theories is very helpful.

    And this is as far as I have got so far. In the future I would love to extend it with the Karma system but there is alot more to do to get this site up and running.

    By timc3 on the
    October 8th, 2006
  9. django with apache2

    One thing that I feel is harder than it should be with django is getting it working with Apache2. Sure the built in webserver is nice for development, but there comes a time when you need to step up and use a webserver for development that you can also deploy the site upon.

    I have used Apache a lot in the past, but recently I have decided to move over to installing everything the Debian way, and this will reflect that. I am going to use python2.3, Apache2 and the version of mod_python that is in stable. You can follow the instructions if you have installed Apache2 and mod_python in otherways after this step if you wish.
    To get Apache2 on debian with mod_python, simply:

    1. apt-get install apache2
    2. apt-get install libapache2-mod-python

    For the rest of the tutorial, I am assuming that you have Django setup correctly, and working with your database. If not, I recommend installing the development version. It is easy to update using svn and there are some features that are better than the stable version I find. Once you have done this you can start to build your site. From then on you can create your apache virtualhost file:

    I have decided to run my django site on a different port, but of course you can run it on different ipaddresses, and with different hostheaders. All you need to do is follow the apache 2 documentation for this. I feel this is already well documented so I will just show how I did it by running on different ports:

    1. Edit the ports file for apache2 to tell it to listen on more than one port:
      vi /etc/apache2/ports.conf
    2. Add this line to tell it to listen on port 8000:
      Listen 8000
    3. Create a new sites file for this new virtual host:
      vi /etc/apache2/sites-available/djangosite
    4. Now we need to put in the configuration details:
      
      
      
      SetHandler mod_python
      PythonHandler django.core.handlers.modpython
      PythonPath "['/home/tim/dev/projects/'] + sys.path"
      SetEnv DJANGO_SETTINGS_MODULE djangosite.settings
      PythonDebug On
      
      
      Alias /media "/var/www/djangosite/media"
      
      SetHandler None
      
      
      
      SetHandler None
      
      
      
      

      This gives us several things:

      • Sets up a virtualhost to listen on port 8000.
      • For the virtual host use mod_python.
      • PythonHandler is told to use Django.
      • Our PythonPath is updated with our site files, in my case my django projects are located in /home/tim/dev/projects/ so this is what I use. Point this to where your django files are kept.
      • Let django know to use the settings file for this project
      • The we setup an alias to serve the media files, as they don’t need to be served through mod_python we turn the handler off for the /media/ location. I will setup my media files in /var/www/djangosite/media
      • Finally tell apache2 not to use mod_python to serve image files.

    5. Now save this file, and enable the site:
      a2ensite djangosite
    6. Now create the webhosting directory, and the symbolic link for the admin directory, and check the permissions:
      mkdir /var/www/djangosite/
      cd /var/www/djangosite/
      ln -s /usr/lib/python2.3/site-packages/django/contrib/admin/media/
      chmod -R 755 /var/www/djangosite
      
    7. The stop and start apache2 on your server (this is for Debian using init.d scripts, but whatever you do stopping then starting is better than a simple reload).
      /etc/init.d/apache2 stop; /etc/init.d/apache2 start

    Once you have done that, check your site by point a webbrowser to the the machine that you have apache2 running on, but at port 8000 for instance if it is a localhost, tryhttp://127.0.0.1:8000.

    One thing that I haven’t talked about is where it is best to place all the files used in creating a django site, and I have yet to read any documentation about this. This is why in the above I am point it to a dev subdirectory from my home directory. I don’t think this is a good idea for a production site, and perhaps it should go in somewhere off /var.

    One thing is for sure, creating seperate directories for media and the actual files is a good idea, and you if you follow the django instructions you can take them up on the recommendation of using a seperate lightweight webserver to just serve these files.

    By timc3 on the
    July 26th, 2006
  10. Top 30 Django Tutorials and Articles

    Here’s a list of 30 helpful tutorials and/or articles on the Django web framework. This was written as an answer to the Top 30 Ruby on Rails tutorials and it is really helpful when you are learning Django. Hopefully this will help it get even more support.

    read more | digg story