Configuring PyCharm, Django and Vagrant

I’ve written about doing development on virtual machines and how to set up Vagrant to run Django. I’ve also been using PyCharm CE for awhile to do simple Python development. Now I’m doing more Django and decided to upgrade to the Professional Edition of PyCharm because of all its cool Django specific features. JetBrains touts you can use it with Vagrant, and built in features to do that. They have tutorials on configuring PyCharm to work with Vagrant and how to use it with Django, but not how to do both.

Turns out this isn’t as simple as it could be and no one has written a comprehensive tutorial on how to do it.

Here it is.

This tutorial will take you from having nothing to having a new Django PyCharm project running on a Vagrant VM.

Create Your Vagrant Virtual Machine

Since I’ve already written how to create a Vagrant VM to do Django development I’m going to assume you are at the same point you were at the end of that tutorial. You have a vagrant instance created. The vagrant directory shares a folder with the server. This article going to call that folder [VagrantFolder]. Any where you see that substitute your folder’s name.

The application I’m creating during this tutorial is called “session_manager”. You should substitute the name of your app.

Launch PyCharm PE and Set-up Vagrant

This tutorial assumes you are using the Professional Edition of PyCharm, as it is the one that has Django support in it. When you launch PyCharm, you’ll get the typical startup window, with its list of known projects and options to create a new one. Now we are going to tell PyCharm about the Vagrant we just created.

Select Configure->Preferences and select Vagrant on the left side.

The only thing you should have to change here is the value of “Instance Folder”. Point it to your [VagrantFolder].

[learn_more caption=”Side Note: Vagrant Not Per Project” state=”close”] I think it is a little strange PyCharm configures Vagrant separate from a project. 

One of the main reasons I use Vagrant is so each project I’m working on has it’s own VM. This means anytime I launch a project, I’m going to want it to have its own vagrant instance. But with PyCharm, I have to come change this preference every time I change Projects.

Actually this may not be true, since a project is “connected” to the Vagrant instance via the “Python Interpreter”, which is bound to one vagrant instance. [/learn_more] 

Create A New Django Project

Close the preferences and go back to the startup window and select Create New Project.

The Create New Project panel will appear for you to fill in.

  • Project name: The name of your new Django Project. In my case this is “session_manager”
  • Location: Click the button on the right and navigate to [VagrantFolder]/django_shared/
  • Project Type: Click the button on the right and select “Django Project”
  • Interpreter: Leave this on its default. (We’re going to have to change it in a minute anyway but you can’t select a remote interpreter in this box).

Click OK to save.

The Django Project Settings panel appears asking for Django specific configuration:

  • Project name: Your project’s name, in my case “session_tracker”.
  • Application name: This has to be different from your project name. {I thought naming them the same was a time honored – if weird – Django tradition.}. I named mine “session_tracker_app”.
  • Templates Folder: I just leave it on the default.
  • Enable Django admin: I’m leaving this checked for my app.

Click OK to save.

Now PyCharm will do its thing and you’ll have a new Django app/project created in your [VagrantFolder]

[learn_more caption=”Why Can’t I Create A Project With Remote Interpreter?”] While writing this I attempted to create the Python Interpreter first, but the “Config from Vagrant File” didn’t work.

Even if I had managed to create it, you can’t select a remote interpreter in the new project window anyway.

Why can’t I create the Vagrant Interpreter before the project and then select a remote during project Creation?[/learn_more]

Create a Python Interpreter For Our Vagrant

At this point we’ve configured a Vagrant machine and we’ve made a new Django project. We need to launch our VM so we, and PyCharm, can do some configuration.

Select Tools->Vagrant->Up and watch it launch your VM launch in the terminal that appears at the bottom of the project window. If this is the first time, this will take awhile.

We have a VM to run our project on, but PyCharm doesn’t know how to run a project on it. Because my Vagrant is setup to share the “django_shared” folder between the host machine and the VM, our code is on the VM. But if you hit run right now, PyCharm would attempt to run it on your host machine, not the VM. The way to change this, is via the Python Interpreter.

In PyCharm you configure which version of Python to use when running your project. By default this uses your local Interpreter, but we want it to use the one on the VM. We need to create a new Python Interpreter.

Where Is Python Installed? It Matters.

I mentioned PyCharm needs to know which Python to use to run a project. This is true on the VM as much as your local machine. In the next step you are going to be asked where python is installed on the VM.

I’ve done this a couple of times and left that path as PyCharm set it. Using the default “/usr/bin/python” made PyCharm think nothing was installed on the VM and then it would give me errors and make me install packages until it was configured right. One of the things I had to do to make it work was to tell PyCharm to install Django, even though my Vagrant file had installed Django.

That seemed so strange I decided to see where python actually was on my VM. Once I did that and set Python Interpreter Path correctly, PyCharm knew Django was installed and didn’t give me any errors.

If you – like me – do not know where python is installed on your VM do this in PyCharm:

Select Tools->Start SSH Session…

Select “Vagrant at [VagrantFolder]” from the list that appears. A terminal will open at the bottom of the screen.

Then do this:

Last login: Sat Feb 22 21:57:54 2014 from 10.0.2.2
vagrant@lucid64:~$ which python
/usr/local/bin/python
vagrant@lucid64:~$

Copy that path for use in the next step.

Create A New Python Interpreter

  • Open Preferences.
  • Select Project Interpreter -> Python Interpreter on the left side. You should see a list of existing Interpreters.
  • Click the + button at the bottom of the list to create a new one.
  • A popup list of Interpreter paths will appear for you to select from. Pick the option, “Remote…”
  • When you do, you’ll get a new window to configure the Remote Python Interpreter. Click “Fill from vagrant config” and select the Vagrant file from [VagrantFolder]. PyCharm will fill in the values of the form.
  • Name: Give your new interpreter a meaningful name.
  • Python interpreter path: where python is installed on the VM.

Click OK to save.

[box type=”warning”] Vagrant Needs to be Up.

If you didn’t Vagrant Up before this, “Test Connection” won’t work and you’ll get a warning when closing the panel. If that happens, close prefs, and use Tools->Vagrant->Up to launch your VM.[/box]

Now PyCharm should know about your VM’s setup. It should show you a list of installed packages. If you are missing something, error messages will appear at the bottom and you can click them to install what it thinks you are missing. If there are no packages listed, try closing and reopening the Preferences window.

ProjectInterpreterWithPackages

 

Click OK to close the Preferences Window.

Configure Your Project to Use the Correct Interpreter

PyCharm now knows about our VM’s Interpreter, we need to tell our project about it and configure things so it will run our Django application in our browser when we click the Run button.

  • Select Run->Edit Configurations…
  • Select the configuration on the right PyCharm created for us. In my case it was called “session_tracker”.
  • Change “Python interpreter” to our newly created one.
  • A new field will appear. Click the button next to “Path mappings”.  A new window will appear to let you create your mappings.
  • Vagrant shares a local directory with the VM. My Vagrant file is configured so a folder is called “django_shared” in our [VagrantFolder] locally, and “django_shared” in the home directory on the VM are the same. You need to enter the full paths of each of those in the “Edit Path Mappings” window. Click the + button to create a new mapping, then enter the values for the mapping on each side.

[learn_more caption=”I Hate Typing Paths”] I hate typing paths, so to make it easy I navigated to the local directory in the OSX Terminal and typed “pwd”, which spit out the full path. I copied that and pasted it into the left side of the Path Mapping Window.

Then I vagrant sshed into my vagrant box, navigated to the django_shared directory and executed “pwd” again. Copied that value and pasted it in the right side.

If you used my script, this value will always be “/home/vagrant/django_shared”.[/learn_more]

Edit_Path_Mappings

Click OK to save the paths.

Back in the configuration window.

  • Click the checkbox to turn on “Run browser:”. Doing this will open your browser to that location whenever you run the Django application and start debugging.
  • For Host: enter 0.0.0.0

This took me a long time to figure this one out. You have to set your host – which is what gets used by Django’s runserver command – to 0.0.0.0. If you leave it the default, you won’t be able to connect to Django from your machine.

Why? According to this blog post, which gave me the idea, it is “because Django webserver bounds the ip to 127.0.0.1, which is loopback in the Ubuntu guest”.

Click OK to save.

That, finally, is it. If you click run or menu Run->Run, your browser should open and you should see the default Django server message.

I just spent five hours writing this tutorial when I’d sat down to start working on my session_manager Django app. I did it because it took me forever to figure out how to make all this work and I wanted it to be easier for the next guy. Please give me feedback if you do find it useful and of course share it.

Setting Up Django on Vagrant

[box type=”warning”]Since I created this post things broke. Namely checking out the latest versions of the Chef cookbooks introduced a whole rat’s nest of dependencies. I spent a day trying to figure them out, but finally decided to just do provisioning via a shell script.

The repository has been updated so the latest version uses the new shell script. If you want the Chef version, it was tagged “v1WChef”.
[/box]

In a previous post I talked about how to do WordPress Development right by using Vagrant to create a virtual machine to do your development in.

I’ve been wanting to improve my Django skills and have a project I want to use it for, so I plan to use the same principle and do my Django coding in a VM using Vagrant.

Figuring out how to do this quickly, easily and reliably was more complicated than I expected. I owe a great debt to Smiley Creatives’ article “SETUP A DJANGO VM WITH VAGRANT, VIRTUALBOX, AND CHEF” and a comment by juanje on how to create a Chef cookbook to install Django.

My goal was to create something where I could run a script and have a whole new development environment for Django set up.

The Vagrant Django Script

If you don’t care how it works, but just want to use it, then do these steps.

1. Clone the repository to your machine.

I’ve created a git repository on bitbucket.org with all the files you need. Just execute this command.

git clone https://bitbucket.org/rondavis007/django-vagrant-creation-scripts.git

This will create a folder on your machine. This folder is not where you are going to run Vagrant from. Rather it is a source folder for creating another folder to run Vagrant from and do your Django development.

2. Create a Target Folder

Make a directory for your development. Note the path to that directory.For our purposes, we’ll assume you want this directory to be next to the directory just created by the git clone command in step 1.

mkdir VMTEST

3. Run the Create Django VM Script

In the folder that was created by git you will find a script ‘create_django_vm.py’. Execute this script with the path to the directory you created in step 2.

cd django-vagrant-creation-scripts/
python create_django_vm.py ../VMTEST/

If you look in the new directory you’ll see something like this:

-rw-r–r– 1 rondavis 2920 Feb 5 14:39 Vagrantfile
drwxr-xr-x 12 rondavis 408 Feb 5 14:39 cookbooks
drwxr-xr-x 2 rondavis 68 Feb 5 14:39 django_shared

You have a new Vagrantfile, a folder full of Chef cookbooks, and a django_shared folder that will be shared with the VM.

4. Move To Your New Directory and Vagrant Up

That’s it, you are ready to go.

cd ../VMTEST/
vagrant up

That’s it. There will be a bunch of Vagrant launching text, but when it’s finished you can:

vagrant ssh

You’ll find a directory in your home directory named “django_shared”. This is the same as the folder “django_shared” in the directory you just vagrant sshed from.

From here you can do all your django commands on your VM. Edit the files on your host OS, and view the app via your browser.

Running Django On Your VM

Let’s make sure our development environment is able to run Django by duplicating the first steps of the Django Tutorial.

Once you are logged in:

vagrant@lucid64:~$ cd django_shared/
vagrant@lucid64:~$ django-admin.py startproject mysite
vagrant@lucid64:~$ cd mysite
vagrant@lucid64:~$ python manage.py runserver 0.0.0.0:8000

First we move into our shared directory, then we create a new Django project with the django-admin.py script. Then move into the newly created app folder and run the server.

Now go back to your browser and point it to http://localhost:8000/ and you should get the standard Django welcome.

Welcome_to_Django

A special note about the runserver command on your VM. You can’t just use the default ‘manage.py runserver’ because the VM won’t let that be shared. Instead you must tell it to run the server on 0.0.0.0:8000 to let it be seen outside the VM

I think the code that makes all this happen is well documented, so I won’t go over it all here. Let me know if you use this script and how you like it.