Creating and managing Django projectsprof

What this tutorial is about?

Tutorial explains how to create and run Django projects with PyCharm and also covers Project tool window and navigation.

What this tutorial is not about?

It does not teach you Python and Django.

Before you start

Make sure that:

  • You are working with PyCharm Professional Edition 4.0 or higher. It can be downloaded here.
  • At least one Python interpreter, version from 2.4 to 3.3 is properly installed on your computer. You can download an interpreter from this page.

This tutorial has been created with the following assumptions:

  • Python 3.4.1
  • Django 1.7.0 or higher
  • Default Windows keymap. If you are using another keymap, the keyboard shortcuts will be different.
  • The example used in this tutorial is similar to the one used in Django documentation.

Sample project can be downloaded from here.

Creating a new project

Actually, all new projects are created same way: by clicking the Create New Project button in the Quick Start area of the Welcome screen.


If you have an already opened project, create a new one by choosing File → New Project.... Then, select the desired project type (here it is Django). Specify the project name and location, the Python interpreter to be used for this project (remember, having at least one Python interpreter is one of the prerequisites of this tutorial!)and the Python application name (here it is polls)


Click Create - the Django project is ready.

Exploring project structure

As mentioned above, basically, the stub project is ready. It contains framework-specific files and directories. Same happens when you create a project of any supported type, be it Pyramid, or Google App Engine.

Let's see how the structure of the new project is visible in the Project tool window.

Project view of the Project tool window

This view is displayed by default. It shows the Django-specific project structure: polls and mysite directories; also, you see the and files.

You cannot see the .idea directory in this view:


Project Files view of the Project tool window

If for some reasons you would like to see contents of the .idea directory, choose the view Project Files: as you see, this view shows same directories and files, plus .idea directory, since it is located under the project root.


Let's return to the Project view.

What do we see in the Project view?

  • mysite directory is a container for your project. In the Project view it is denoted with bold font.
  • This is a command-line utility that lets you interact with your Django project. Refer to the product documentation for details.
  • The nested directory mysite is the actual Python package for your project.
  • mysite/ This empty file tells Python that this directory should be considered a Python package.
  • mysite/ This file contains configuration for your Django project.
  • mysite/ This file contains the URL declarations for your Django project.
  • mysite/ This file defines an entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.
  • Finally, the nested directory polls contains all the files required for developing a Django application (at this moment, these files are empty):
    • Again, polls/ tells Python that this directory should be considered a Python package.
    • polls/ In this file, we'll create models for our application.
    • polls/ In this file, we'll create views.
  • templates directory is by now empty. It should contain the template files.
  • The nested directory migrations contains by now only the package file, but will be used to propagate the changes you make to your models (adding a field, deleting a model, etc.) into your database schema. Read the migrations description here.

Note that you can create as many Django applications as needed. To add an application to a project, run the startapp task of the utility (Tools→Run task - startapp on the main menu).

Configuring the database

Now, when the project stub is ready, let's do some fine tuning. Open for editing To do it, select the file in the Project tool window, and press F4. The file is opened in its own tab in the editor.

Specify which database you are going to use in your application. For this purpose, find the DATABASES variable: click Ctrl+F, and in the search field start typing the string you are looking for. Then, in the 'ENGINE' line, add the name of your database management system after dot (you can use any one specified after comment, but for the beginning we'll start with sqlite3.)

In the 'NAME' line, enter the name of the desired database, even though it doesn't yet exist.


Launching the Django server

Since we've prudently chosen sqlite3, we don't need to define the other values (user credentials, port and host). Let's now check whether our settings are correct. This can be done most easily: just launch the runserver task of the utility: press Ctrl+Alt+R, and enter task name in the pop-up frame:


Follow the suggested link and see the following page:


Creating models

Next, open for editing the file, and note that import statement is already there. Then type the following code:

from django.db import models

   # the following lines added:

   import datetime
   from django.utils import timezone

   class Question(models.Model):
   question_text = models.CharField(max_length=200)
   pub_date = models.DateTimeField('date published')

   def __str__(self):
       return self.question_text

   def was_puplished_recently(self):
       now =
       return now - datetime.timedelta(days=1) <= self.pub_date <= now

   was_puplished_recently.admin_order_field = 'pub_date'
   was_puplished_recently.boolean = True
   was_puplished_recently.short_description = 'Published recently?'

   class Choice(models.Model):
   question = models.ForeignKey(Question)
   choice_test = models.CharField(max_length=200)
   votes = models.IntegerField(default=0)

   def __str__(self):
       return self.choice_test

Actually, you can just copy-paste, but typing is advisable - it helps you see the powerful PyCharm's code completion in action:


Creating database

We have to create tables for the new model. For this purpose, we'll use the magic Ctrl+Alt+R to invoke the console. First command to perform is makemigration:


Thus you've told Django that a migration and two new models have been created, namely, Choice and Question:


Next, after the prompt, type sqlmigrate polls 0001:


Finally, run migrate command to actually create these tables in your database:


Performing administrative functions

First thing, create a superuser. To do that, type the superuser command in the console, specify your email address, and password:


Since we've decided to enable site administration, PyCharm has already uncommented the corresponding lines in the file.

However, we need to enable editing functionality for the admin site. To do that, open the file in the polls directory for editing, and enter the following code:

from django.contrib import admin

from .models import Choice, Question

class ChoiceInline(admin.TabularInline):

   model = Choice

   extra = 3

class QuestionAdmin(admin.ModelAdmin):

   fieldsets = [

       (None,               {'fields': ['question_text']}),

       ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),


   inlines = [ChoiceInline], QuestionAdmin)

Again pay attention to the code completion:


Preparing run/debug configuration

We are now ready to go to the admin page. Sure, it is quite possible to run the Django server, then go to your browser, and type the entire URL in the address bar, but with PyCharm there is an easier way: use the pre-configured Django server run configuration with some slight modifications.
To open this run/debug configuration for editing, on the main toolbar, click the run/debug configurations selector, and then choose Edit Configuration (or choose Run→Edit Configurations on the main menu):


In the Run/Dug Configuration dialog box, give this run/debug configuration a name (here it is mysite), enable running the application in the default browser (select the check box Run browser) and specify the page of our site to be opened by default(here this page is


Launching the admin site

Now, to launch the application, press Shift+F10, or click screenshots/run.png?version=1&modificationDate=1403263710000 on the main toolbar to open the standard Django's site administration page:


After you log in, the administration page is displayed. It has a section Authentication and Authorization (Groups and Users), but Polls is not available. Why so?

We must tell admin that Question objects have an admin interface; to do that, let's open the file polls/ for editing (select it in Project view and press F4), and type the following code:

from django.contrib import admin

from .models import Question #this line added line added

Refresh the page and see that Polls section with Questions appeared:


Click Add to create some questions.

However, each question has a number of choices, but choices are still not available. Again, open for editing the file polls/ and change it as follows:

from django.contrib import admin

from .models import Choice, Question

class ChoiceInline(admin.TabularInline):

   model = Choice

   extra = 3

class QuestionAdmin(admin.ModelAdmin):
   fieldsets = [

       (None,               {'fields': ['question_text']}),

       ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),


   inlines = [ChoiceInline], QuestionAdmin)

Now look at the Change question page:


Writing views

Open the file polls/ for editing and type the following Python code:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.") 

Next, add a new file to the polls directory with the name and type the following code in it:

from django.conf.urls import url

from . import views

urlpatterns = [

   url(r'^$', views.index, name='index'),


Next, open for editing the file mysite/ (which PyCharm has already created for you) and add a URL for the index page. You should end up with the following code:

from django.conf.urls import include, url

from django.contrib import admin

urlpatterns = [

   url(r'^polls/', include('polls.urls')), #this line added

   url(r'^admin/', include(,


Now, open the page and enjoy:


Next, let's add more views. Again, add the following code to the file polls/

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

If you now open the corresponding pages in your browser, you will see, for example:


Creating templates

As you see, the design of these pages if hard-coded in views. So, to make it more readable, you have to edit the corresponding Python code. Let's then separate the visual representation of the output from Python - to do that, let's create templates.

Open for editing the file polls/ and change the method index (by the way, pay attention to the import assistant that helps you create import statements).

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
   template_name = "polls/index.html"
   context_object_name = "latest_question_list"

   def get_queryset(self):
       return Question.objects.filter(

class DetailView(generic.DetailView):
   model = Question
   template_name = "polls/detail.html"

   def get_queryset(self):
       Excludes any questions that aren't published yet.
       return Question.objects.filter(

class ResultsView(generic.DetailView):
   model = Question
   template_name = "polls/results.html"

def vote(request, question_id):
   p = get_object_or_404(Question, pk=question_id)
       selected_choice = p.choice_set.get(pk=request.POST['choice'])
   except (KeyError, Choice.DoesNotExist):
       return render(request, 'polls/detail.html', {
           'question': p,
           'error_message': "You didn't select a choice",
       selected_choice.votes += 1
       return HttpResponseRedirect(reverse('polls:results', args=(,)))

The first thing you notice is an unresolved reference to the page index.html:


PyCharm suggests a quick fix: if you click the yellow light bulb, or press Alt+Enter, the corresponding template file is created in the templates folder (note that PyCharm also creates the directory polls where this template should reside):


By now, the file index.html is empty. Add the following code to it:

{% load staticfiles %}

<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

{% if latest_question_list %}


   {% for question in latest_question_list %}

       <li><a href="{% url 'polls:detail' %}">{{ 
question.question_text }}</a></li> {% endfor %} <ul> {% else %} <p>No polls are available.</p> {% endif %}

Note code completion in the template files! When you type the opening {%, PyCharm adds the matching closing one %} automatically, placing the caret at the location of the future input:


Code completion is also provided for the HTML tags:


Pay attention to the icons screenshots/django_guide/h_icon.png and screenshots/django_guide/py_icon.png that appear in the left gutter of the files and index.html respectively:


These icons enable you to jump between a view method and its template straight away. Read more about this kind of navigation here.

Using a stylesheet

As you can see in the view file index.html, there is a reference to a stylesheet, and it's unresolved:


To resolve this reference, do the following:

  • In the Project view, select the Python package polls, and then press Alt+INSERT.
  • On the pop-up menu that appears, choose Directory, and specify the name of the directory structure static/polls.
  • Next, choose the innermost directory polls, press ALT+INSERT, choose the option Stylesheet, and enter style in the dialog box that opens.

Provide some contents to the created stylesheet, depending on your preferences. For example, we'd like to see a bulleted list of questions colored green:

li a {
   color: green;

Here we are!

Now let's check the list of available polls. Our admin site is already running, and the easiest way to visit the page that contains the list of polls (the index page), is to specify its URL in the address bar of the browser — instead of /admin/, type /polls/:


Test it...

Now let's see how PyCharm helps simplify to test your application.

There is already the file (see the image in the section Project view). By now, this file is empty. Naturally, it is advisable to place the new tests in this particular file. For example, type the following code:

import datetime
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.utils import timezone
from .models import Question
def create_question(question_text, days):
   time = + datetime.timedelta(days=days)
   return Question.objects.create(question_text=question_text,

class QuestionViewTests(TestCase):
   def test_index_view_with_no_questions(self):
       If no questions exist, an appropriate message should be displayed.
       response = self.client.get(reverse('polls:index'))
       self.assertEqual(response.status_code, 200)
       self.assertContains(response, "No polls are available.")
       self.assertQuerysetEqual(response.context['latest_question_list'], [])

   def test_index_view_with_a_past_question(self):
       Questions with a pub_date in the past should be displayed 
on the index page. """ create_question(question_text="Past question.", days=-30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question.>'] ) def test_index_view_with_a_future_question(self): """ Questions with a pub_date in the future should not be displayed
on the index page. """ create_question(question_text="Future question.", days=30) response = self.client.get(reverse('polls:index')) self.assertContains(response, "No polls are available.", status_code=200) self.assertQuerysetEqual(response.context['latest_question_list'], []) def test_index_view_with_future_question_and_past_question(self): """ Even if both past and future questions exist, only past
questions should be displayed. """ create_question(question_text="Past question.", days=-30) create_question(question_text="Future question.", days=30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question.>'] ) def test_index_view_with_two_past_questions(self): """ The questions index page may display multiple questions. """ create_question(question_text="Past question 1.", days=-30) create_question(question_text="Past question 2.", days=-5) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question 2.>', '<Question: Past question 1.>'] ) class QuestionIndexDetailTests(TestCase): def test_detail_view_with_a_future_question(self): """ The detail view of a question with a pub_date in the future
should return a 404 not found. """ future_question = create_question(question_text='Future question.', days=5) response = self.client.get(reverse('polls:detail', args=(,))) self.assertEqual(response.status_code, 404) def test_detail_view_with_a_past_question(self): """ The detail view of a question with a pub_date in the past should
display the question's text. """ past_question = create_question(question_text='Past Question.', days=-5) response = self.client.get(reverse('polls:detail', args=(,))) self.assertContains(response, past_question.question_text, status_code=200)

To run this test, right-click the backgrould of the file in the editor and then choose the option Run Tests:polls.tests, or just press CTRL+SHIFT+F10:


The test results show in the Test Runner tab:



This brief tutorial is over. You have successfully created and launched a simple Django application.

Let's repeat what has been done with the help of PyCharm:

  • a Django project and application has been created
  • the Django server launched
  • a database configured
  • models, views and templates created
  • the application launched
  • tests created and executed