My Eclipse Setup for Django

Eclipse LogoDocumenting my Eclipse setup as I install onto a fresh Ubuntu 11.04 machine.

First, is the choice of Eclipse package. There are several that will work for Python/Django – basically any of the Language IDE focused bundles. This time I am using the Java EE setup (v3.7.1), but I have also installed the standard Java and C/C++ builds with success.

I wish that there was an install procedure for Eclipse that would setup the menus, etc. The package available in the Ubuntu Software Center is usually an older version (currently 3.5) and is a basic install only. It is up to the user to add the additional features desired. Instead, I download the package, extract to /opt, and setup the menus myself.

Next is Aptana Studio 3. This includes PyDev (which supplies Python and Django functionality), web tools, Ruby support, and other goodies. For Python/Django support only, I have used the standalone PyDev install instead. However, once PyDev is installed, the Aptana install complains if installed later.

Also important is version control support. Eclipse comes with CVS included, and clients for other systems are available. Since I use Subversion, I install the Subclipse add-in from Tigrs. Check the version numbers of both your Eclipse and svn installs to select the correct Subclipse package. Eclipse will complain about JavaHL not being available the first time SVN is used. There is a setting in Eclipse (under Team/SVN) to switch to the SVNKit client.

I have also used Eclipse SQL Explorer for database access. It is a bit of a fight to get the proper drivers and configuration all figured out, but worth it to have DB commands within the Eclipse environment here. Read more about SQL Explorer in this earlier post.

That is pretty much it. I may at a later date talk about setting up virtual environments in Eclipse, so stay tuned.

Any questions or suggestions? Please post a comment below.

Satchmo

I’m setting up an online store using the popular Django application Satchmo. My goal is to build a site to sell my wife’s gourd art, but I’d also like to get a store in my portfolio to show to future clients.

Here are a couple of hints on the installation.

URLS

After I installed everything, I ran the satchmo_check command to confirm the configuration and received this error:

Unable to resolve url. Received error- Empty module name

Turns out I had missed a setting when modifying the skeleton settings.py file. Be sure to set ROOT_URLS to the correct setting for your installation. It was blank in the sample file.

CSRF

My first experiment was with the trunk version, currently 0.9-2. However, for the installation of my store, I used the latest released version, 0.9-1. Should be close, right? It probably is, but a big thing to note is that this version does not use the CSRF middleware that is included in my default setup. I didn’t get very far until I commented that module in settings.py.

I’ll post more as I run across things.

Class-Based Views – A ListView Example

I put this here mostly for my own documentation.

Before:

@permission_required('training.view_signupdetail') 
def class_history_attend(request,class_id):
    
    tc = get_object_or_404(TrainingClass,id=class_id)
            
    queryset = SignupDetail.objects.filter(schedule__training_class = tc,attended = True).order_by('session__user__username')
    
    params = {'queryset': queryset,
              'template_name': 'class_history.html',
              'extra_context': {'tc': tc}}
    return object_list(request, **params)    

After:

class ClassHistoryAttendView(ListView):
    ## Set the template name
    template_name = 'class_history.html'  

    ## Override dispatch to apply the permission decorator
    @method_decorator(permission_required('training.view_trainingclass'))
    def dispatch(self, *args, **kwargs):
        return super(ClassHistoryAttendView, self).dispatch(*args, **kwargs)  
    
    ## Define get_queryset to bring in the supplied class number and build the query
    def get_queryset(self):
        self.tc = get_object_or_404(TrainingClass,id=self.kwargs.get('class_id',None))
        return SignupDetail.objects.filter(schedule__training_class = self.tc,attended = True).order_by('session__user__username')
    
    ## Override get_context_data to add the class number to the context for use by the template
    def get_context_data(self, **kwargs):
        context = super(ClassHistoryAttendView, self).get_context_data(**kwargs)
        context['tc'] = self.tc
        return context

UPDATE:

The override of dispatch allows the application of the permission decorator. Note the @method_decorator wrapper around the traditional view decorator for permission use.

The other two method overrides are necessary to access the self instance of the object.

An easier example still uses the permission override, but others are not needed.

Before:

@permission_required('b2c.view_event')
def list_event(request):
    params = {'queryset': Event.objects.all(),
              'paginate_by': DEFAULT_PAGINATION,
              'template_name': 'event_list.html'}
    return object_list(request, **params)

After:

class ListEventView(ListView):
    ## The basics
    template_name = 'event_list.html'  
    paginate_by = DEFAULT_PAGINATION
    queryset = Event.objects.all()

    ## Override dispatch to apply the permission decorator
    @method_decorator(permission_required('b2c.view_event'))
    def dispatch(self, *args, **kwargs):
        return super(ListEventView, self).dispatch(*args, **kwargs) 

Note that the paginate_by variable is set in this example.

Also

These are the imports needed:

from django.views.generic import ListView
from django.utils.decorators import method_decorator

In urls.py, adjust the definition to call the as_view method of the class:

url(r'^list_event/$',ListEventView.as_view(),name='event_list')

Class-Based Views – Am I Doing It Right?

I thought this would be simpler than it turned out to be. Here’s the ‘before’ code:

def start(request):
    ## clear out all session variables
    request.session['username'] = None
    
    return render_to_response('start.html',
                              context_instance=RequestContext(request) )

This view resets a session variable and sends out a template. Not too tough.

Next, is my first attempt to convert to a class-based view:

class StartView(TemplateView):
    template_name = "start.html"
    self.request.session['username'] = None

However, I quickly learned that ‘self’ is not available here. So, I picked a method, and overrode it to include my reset code:

class StartView(TemplateView):
    template_name = "start.html"
    
    def render_to_response(self,context, **response_kwargs):
        self.request.session['username'] = None
        return super(StartView, self).render_to_response(context, **response_kwargs)

Sure, this works, but there is likely a better way.

Please leave your suggestions in the comments below.

Django on Dreamhost

Dreamhost LogoThere are many posts that outline the steps to deploy a Django app onto a Dreamhost shared server. This is my experience.

I used a couple of pages as references, both to help me know what to do and to learn what not to do. Installing django 1.3 on DreamHost on oscarcp.com helped with the virtualenv setup, and the Passenger and WSGI section on the Dreamhost Wiki page on Passenger showed how to use the correct python interpreter.

Python

I’ve previously setup the Python 2.6.5 interpreter to be my default on Dreamhost (see this post), so I’m not sure what version they offer currently as the default. Be sure that the version you are running is supported by your desired Django version.

Setup Passenger for you Domain

It’s an option on the Dreamhost panel. When editing your domain, check the box labeled “Passenger (Ruby/Python apps only)“. This will add a /public directory in the domain root. (It may take a few minutes for this work to finish.)

Install Virtualenv

There is a version of virtualenv available on Dreamhost which will work fine. However, I wanted the latest, so I downloaded and installed it. First, I opened a terminal window and ssh’ed to my Dreamhost account. I have a downloads folder setup, so I switched to that before running the download. (As of this writing, 1.6.4 is the latest released version.)

wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz
tar -xvf virtualenv-1.6.4.tar.gz
python setup.py install

Create the Virtual Environment for the Project

My naming convention for virtual environments is to use the project name followed by ‘env’. Pretty creative, huh? Since my project is an art gallery, I called it ‘galleryenv’.

Before running the command, switch to the root directory for the domain. This is the folder containing the /public directory created by the Passenger selection earlier. The Dreamhost default is to name this the same as the domain, but yours may be different.

virtualenv envname --no-site-packages

The –no-site-packages argument is pretty important, as it instructs virtualenv to ignore all python packages installed in the base interpreter. Everything you need for the project should be installed in this new environment. This means that your project will be insulated from changes to the base install, and will allow different projects/environments to use different versions of the same packages.

Next, activate the interpreter in the virtual environment you just created. Basically, you’re switching to this new copy of Python rather than the default for your account.

source envname/bin/activate

Your command prompt should now be prefixed with the name of the environment.

Run Django Setup Script? I Say No

Dreamhost provides a script, django-setup.py, that will create your settings file with database settings and the passenger_wsgi.py file for your application. This works pretty well for a new project, but most of the work has to be backed out when an existing application using a different directory structure or settings is being setup. Since I develop my projects on a local development machine (as should you), this isn’t much help. Instead, there are just a few manual steps to perform that will get things ready to go.

Also, you’ll notice that we haven’t install Django yet. Since we used the –no-site-packages option when creating the virtual environment, any Django version installed on your account earlier will not be accessible while you are using the new interpreter. The Dreamhost script won’t run unless Django and the MySQL library for Python are installed. No worries! We’ll get to that soon enough.

Bring On the Source code

At this point, it is time to load the source for your Django project onto the server. My convention is to create a directory with the project name in the root directory for the domain – so mine would be called ‘gallery’. You can put these wherever you like, just remember the path for a later step.

I use the Subversion version control system, also provided by Dreamhost, to store my code, so I would use the ‘svn copy’ command to install my source code. Any VCS or DVCS is fine, or the age old FTP approach will work as well.

PIP and Requirements

I’ve just started using PIP recently, although it has been around the Python world for a while. PIP is a general Python install tool, and we’re going to use it to quickly install the libraries we need for our application. Since it is installed with virtualenv (at least in 1.6.4), it is already setup and ready to go.

Before this step, ensure that the virtualenv interpreter is still activated – see the source command above. The goal is to install the needed Python libraries only for this environment and not for use by the default Python install.

PIP offers the option to include a list of libraries to be installed in a batch run. Following convention, I’ve included a file with my application called requirements.txt. Here’s what mine looks like:

Django<1.4
PIL
django-photologue

First, I want to install the latest release of Django 1.3, so I ask for the most recent less than v1.4. Next, I need to use the Python Image Library, or PIL. (This library has operating system dependencies that will need to be satisfied before the install.) Finally, the package django-photologue is requested. Prepare your own requirements in this format.

To run PIP with your requirements, use the following syntax:

pip install -r requirements.txt

It's just that easy! Watch the output carefully for any errors or warnings.

Since I'm using MySQL for my database on the server, I also need the mysql-python library.

pip install mysql-python

Passenger Configuration

The django-setup.py script I mentioned earlier builds a file called passenger_wsgi.py that links Apache to the django application. For your install, you can either run the script, or use my example as a starting point. Either way, some edits will be needed to use the virtual environment. Here's is my file:

import sys, os
INTERP = os.path.join(os.environ['HOME'], 'gallery.gentryart.us', 'galleryenv', 'bin', 'python')
if sys.executable != INTERP:
    os.execl(INTERP, INTERP, *sys.argv)
sys.path.append(os.getcwd())
sys.path.append(os.path.join(os.getcwd(),'gallery'))
os.environ['DJANGO_SETTINGS_MODULE'] = "gallery.settings"
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

The second line of the script sets a variable (INTERP) to the path of the virtual environment's python interpreter. Basically, the os.path.join command builds the path using the directory names we created earlier. Starting at the home directory, we add in the domain name and the environment name, followed by 'bin/python'. Replace my gallery references with your application's directories.

Lines 3 and 4 will switch to the new python interpreter referenced by the variable.

The sys.path.append lines include our application directory in the search path used by Python, and the next line points to our settings.py file. In these lines, replace 'gallery' with the path to your application source code.

passenger_wsgi.py should be placed in the root directory for the domain. Feel free to copy my example and edit to taste.

Static Media

Better bloggers than I have written about serving static media, and this is just one of many ways to do it. Since I store these files (CSS, JS, images) in version control, they are installed in the application directory created earlier. A simple symbolic link will point Apache to the correct files.

First, switch the the /public directory located in the root directory for the domain. Then, setup the symbolic link to refer to the files. Since my files are located in a directory called 'static', this command takes care of it.

ln -s ../gallery/static static

Next, setup a link for the Django admin media.

ln -s ../galleryenv/lib/python2.6/site-packages/django/contrib/admin/media admin_media

One Last Thing

Since I had already been running my app on this domain using a pre-passenger method for hosting Django, I had a leftover (and hidden) .htaccess file that was messing things up. A quick note to the Happy Dreamhost Support Team and they found and fixed the problem. No .htaccess settings are needed for this type of configuration.

Ready To Go

Hopefully, everything is working for you at this point. In my case, Django came up and told me my database settings were wrong, but I see that as progress. The site is now working fine.

Good luck!

http://gallery.gentryart.us

Database Not Available

The Situation:

During certain processes, such as fiscal year end and software upgrades, my Oracle database is placed in restricted session. As expected, an attempt to use the Django application results in the error “ORA-01035: ORACLE only available to users with RESTRICTED SESSION privilege”. This error is thrown from deep within the ORM code.

The Question:

How can I grab this error within my application to be able to send a meaningful error message back to the user instead of the 500 page? I’d also like to stop the email sent to the administrator (me) each time this error is triggered.

TDD Works Better Up Front

For the Django app I deployed last month, I had started the process using a Test Driven Development (TDD) approach. In a nutshell, it means that tests are written before a feature is coded. This went well at the beginning, but as crunch time neared, the tests were thrown by the wayside and code was tossed in as needed.

Now that I’m in this Django upgrade project, I decided to go back and complete the tests before starting the upgrade work. It is now three weeks later, and I still have much to do (working on my own time – not during work hours). However, I’m really enjoying the satisfaction that passing a well written test can bring.

My hope is that my next project will be more TDD compliant, as I am learning the skills now that I need to write quality tests quickly.

Next Application Please

For my Django upgrade project, I see several steps for each of the four applications:

  • Review the code and update on my laptop
  • Pass to the designer for any changes he needs to make (probably not many related to the Django version change)
  • Move the code to the DEV server to test Apache and Oracle compatibility
  • Deploy to QA and test the heck out of it.
  • Deploy to production and hope nobody notices

The first time I work on the DEV server, there will also be virtualenv things to work out.

Application #1 has gone through the first step. so I’m now starting work on app #2. It’s a little bigger, so this may take a little longer. Keep in mind that this first step is all being done in my spare time.

Work has been pretty crazy, so I haven’t had time to talk with the server admins about virtualenv or Oracle 11g. Hope to get to it soon.

And As If Version Upgrades Weren’t Enough…

In addition to the Django version upgrades I’m in the middle of, I also am facing a scheduled upgrade of the Oracle version used by my apps. They share an Oracle instance with the enterprise application that runs the business, so these smaller systems upgrade on the big guy’s schedule.

Currently, all run on Oracle 10g, and the DB platform upgrades to 11g in July. Shouldn’t be a big deal, but I don’t have enough experience with the Oracle client running on the web servers, or with the Python interface to Oracle.

This project starts next week.

Django Framework 1.3 Fixes

Looking through the release notes for v1.3, I don’t see any backwards incompatible issues that affect me. As for new features, there is an index that is now used on the session table that I can add, and the much heralded class-based views are now available.

Looking through the deprecation list, I did find a couple of things to check. First, an upcoming change to the url template tag warrants a look through my code, and the eventual removal of the function-based generic views means that I can either fix them now or during the next upgrade.

Hopefully, this will be quick, not only on my first, uncomplicated application, but the more complicated ones I’ve written more recently.