Categories
geek

URLs, Models, Views, Templates, and Shell – Useful Snippets for Each

There have been quite a few times when I have resorted to my coding friends and mentors and good ole Prof. Google to teach me how to write the code I needed to get the job done.

In particular, Adam (@adamjt) and Andy (@ashearer) have been right there alongside me helping me out.

Learning Django has been particularly involved because there are so many “in” things to know.  My understanding of Django has come down to the fact that there are 5 things to master in order to code Django and python successfully – the urls, the models, the views, the templates, and the python shell (command line interface).  I’ll touch on each one and list something I didn’t get at first until my friends explained it to me or I found it on google.  It is written in the spirit of writing it down so I don’t forget it …

URLS:   All about the media … explained to me by Andy (@ashearer on twitter)

In order to link my templates to the site media such as images and javascript and all that fun stuff I had to follow some specific steps in a very un-PHP manner:

  1. put a special global variable in the settings file of my project:
    MEDIA_URL = ‘/site_media/’
  2. add an extra expression in my urls file:
    (r’^site_media/(?P<path>.*)$’, ‘django.views.static.serve’, {‘document_root’: os.path.join(os.path.dirname(__file__), ‘site_media’)}),
  3. make a directory on the same level as my urls and settings files called “site_media” that holds all my files (which can then contain subdirectories for css, images, javascript that I can include in my links in the template)
  4. link to the MEDIA_URL in the template itself, like so:
    <link href=”{{ MEDIA_URL }}your_stylesheet_name.css” type=”text/css” rel=”stylesheet” />Notice that in the template itself, the {{MEDIA_URL}} is a reverse look-up.  There’s no need to write out the exact relative path to the site_media folder.

MODELS: Optional ForeignKey attribute … explained to me by Adam (@adamjt on twitter)

When I specify a one to many relationship in my models file using an ForeignKey, sometimes I want that relationship to be optional.  Just blank=true or null=true doesn’t work though, you have to use both:

mynamedattribute = models.ForeignKey(MyModel, blank=True, null=True)

This is an optional field, not required, as ForeignKey fields usually are.

VIEWS: Authenticate me … Adam and Django Docs (@adamjt)

Logging users in and out is quite the hassle, but there are some built-in methods that take care of the work for me.  In order to get a user logged in and out, there needs to be a url side of it, a view side, and a template side.  There are more advanced registration and authentication modules out there ( Google code has one I recommend http://code.google.com/p/django-registration/ ) but there are also some short-cuts that come with Django that work very well.

  1. On the urls side, these are the urls that link to the views that are built into django to log users in and out:
    (r’^login/$’, ‘django.contrib.auth.views.login’),
    (r’^logout/$’, ‘django.contrib.auth.views.logout’),
    Teeny sidenote here:  there was a release of django that had the login template moved from registration to admin but referenced the old location in the view, so to fix it I took the non-coding way out and copied the template over to the proper directory
  2. For views that need authentication, “login_required” is an easy way to check for logged in users.  The view file first imports the necessary decorators:
    from django.contrib.auth.decorators import login_required
    from django.contrib.auth import logout
  3. Then the view can either start with login_required:@login_required
    def view(request):
    variable_name=processed_variable
    return render_to_response(
    ‘index.html’,
    {“ElementName”: variable_name}, context_instance=RequestContext(request))
  4. or it can use “if request.user.is_authenticated” within the view (if it came from a login form it will look like the code below):
    def otherview(request):
    if request.method == ‘POST’:
    if request.user.is_authenticated():
    variable_name=request.user.username

    else:
    variable_name=”Not logged in so no name”
    return render_to_response(
    ‘index.html’,
    {“LoggedInName”: variable_name}, context_instance=RequestContext(request))
  5. Then in the template there is the same operator for segments of code that should be displayed for logged in users:
  6. {% if user.is_authenticated %}
    <a href=”/account/”>My Account ({{ user }})</a>
    {% else %}
    <a href=”/login/” >Login or Register</a>
    {% endif %}

TEMPLATES:  Ordering output and Grouping … explained to me by Adam (@adamjt)

For an article-based engine, I needed to group a list of articles in order to show them according to category and then by date within the category.  First I had to order them in the view and then regroup them in the template:

  1. The view is simple enough, generate a variable that stands for all objects in class MyArticle in order by category:
    variable_articles = MyArticle.objects.order_by(“category”)
  2. Pass the variable to the template in the dictionary:
    return render_to_response(‘articles.html’, {‘articles’: variable_articles}, context_instance=RequestContext(request))
  3. Then in the template, I make use of the “regroup” template tag to take the already ordered-by-category articles to order them further by date:
  4. {% regroup articles by category as article_list %}
    {% for article in article_list %}
    <h3>Category: {{article.grouper}}</h3><ul>
    {% regroup article.list by date as datedarticle_list %}
    {% for datedarticle in datedarticle_list %}
    {% ifchanged %}<li>{{datedarticle.grouper.date|date:”F j, Y”}}{% endifchanged %}
    <ul>{% for item in datedarticle.list %}
    <li><a href = “/article/{{item.id}}/”>{{item.title}}</a>, {{item.author}}</li>{% endfor %}
    </ul>

    {% endfor %}</ul><br />{% endfor %}</ul>
    Notice that we had to regroup by category aside from using “order_by” in the view, but that was for the purpose of printing out the attribute by which the variable was grouped.

Finally the

SHELL:  Python shell scripts … figured out through pieces on Google

Using the administration interface is nice since you can see everything neatly represented by menus and drop down fields in a GUI, but there are tasks that are more efficiently accomplished using the command line.  Even that has its limit, in the sense that I could only ever figure out how to give it one command at a time.  A shell script on the other hand will give me the efficiency of the command line with the advantage of being able to write out an automated, saveable, multi-command executable.  You do need to have access to a Linux-type terminal in order to do this (the script starts off with the bash shebang).

  1. Create a file called myscript.sh and chmod it to have execute privileges:
    chmod +x myscript.sh
  2. Create the python environment with the python path and the django environmental setting:
    #!/usr/bin/env python
    import sys, os
    # Add a custom Python path.
    sys.path.insert(0, “/usr/bin/python”)

    # replace myname with your username
    sys.path = [‘/home/myname’] + sys.path

    # Set the DJANGO_SETTINGS_MODULE environment variable.
    os.environ[‘DJANGO_SETTINGS_MODULE’] = “myproject.settings”

    from django.contrib.auth.models import User #for example, this can be any django code

  3. Write in any commands you normally would type into the command line, for example making repetitious code into for loops like so:
    for i in range(1,51,5): # where i is the iterator and range(start,stop,step) – stop is non-inclusive
    article=MyArticle.objects.get(pk=i) #to select all objects with indices 1,6,11 and so forth up to 50
  4. Execute the script from your normal command line:
    ./myscript.sh

And there you have it!