Step 4. Create and Run your first Django project
Before you start
Make sure that the following prerequisites are met:
You are working with PyCharm version 2022.2 or later. If you still do not have PyCharm, download it from this page. To install PyCharm, follow the instructions, depending on your platform.
This tutorial has been created with the following assumptions:
Python 3.10.5.
Django 4.1.
The example used in this tutorial is similar to the one used in Django documentation.
Creating a new project
From the main menu, choose New Project button in the Welcome screen. New Project dialog opens.
, or click theIn the New Project dialog, do the following:
Specify project type Django.
If required, change the default project location.
Select New environment using Virtualenv
Click (More Settings), and specify polls in the Application name field.
Click Create.
Exploring project structure
The newly created project contains Django-specific files and directories.
The structure of the project is visible in the Project tool window:
MyDjangoProject directory is a container for your project. It is denoted with bold font.
manage.py is a command-line utility that lets you interact with your Django project. Refer to the Django documentation for details.
The nested directory MyDjangoProject is the actual Python package for your project.
MyDjangoProject/__init__.py: This empty file tells Python that this directory should be considered a Python package.
MyDjangoProject/settings.py: This file contains configuration for your Django project.
MyDjangoProject/urls.py: This file contains the URL declarations for your Django project.
MyDjangoProject/wsgi.py: This file defines an entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.
The nested directory polls contains all the files required for developing a Django application:
Again, polls/_init_.py tells Python that this directory should be considered a Python package.
polls/models.py: In this file, we'll create models for our application.
polls/views.py: In this file, we'll create views.
templates directory is by now empty. It will contain Django templates.
The nested directory migrations contains by now only the package file _init_.py, but will be used in the future to propagate the changes you make to your models (adding a field, deleting a model, and so on) into your database schema. Read the migrations description here.
Launching Django server
The Django server run/debug configuration is created automatically. If required, you can edit it by selecting the Edit Configurations command in the run/debug configuration list on the main toolbar:
For example, you can choose to open a browser window automatically when the configuration is launched:
Run the MyDjangoProject configuration by clicking . If a browser window does not open automatically, click the link in the Run tool window.
The following page opens:
Writing views
Django views are functions that take web request and return web responses. By convention, views are defined in views.py files inside of project and application directories.
Open the file polls/views.py and type the following Python code:
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You're at the polls index.")The above message will be shown on the index page of the
polls
application.Now we need to instruct the application to render the
index
view.In the polls directory, create the file urls.py and type the following code in it:
from django.urls import path from . import views app_name = 'polls' urlpatterns = [ path('', views.index, name='index'), ]Next, open the file MyDjangoProject/urls.py (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.contrib import admin from django.urls import include, path urlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ]Don't forget to import
django.urls.include
!Open the page http://127.0.0.1:8000/polls/ in your browser. You should see the following text:
Next, let’s add more views. Add the following code to the file polls/views.py:
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)The above views take one argument (
question_id
), and then use it in the responses.Map these new views to URLs by adding patterns in the /polls/urls.py file. The full code should look as follows:
from django.urls import path from . import views app_name = 'polls' urlpatterns = [ path('', views.index, name='index'), path('<int:question_id>/', views.detail, name='detail'), path('<int:question_id>/results/', views.results, name='results'), path('<int:question_id>/vote/', views.vote, name='vote'), ]
If you now open the corresponding pages in your browser, you will see the following:
Creating database
By default, PyCharm automatically creates an SQLite database for a Django project.
We need to create the tables in the database for all applications in the current Django project. To do that, press Ctrl+Alt+R and type migrate
followed by Enter in the manage.py console, that opens.
You should see Process finished with exit code 0
in the console output.
Creating and activating models
Django models define the fields and behaviors of your data. They are represented by Python classes, which are subclasses of the django.db.models.Model
class.
Let's create two models for our polls
app: Question
and Choice
. To do that, open the file polls/models.py, and add the following code after the import statement:
Each model here has class variables represented by instances of a Field
class:
The
Question
model:question_text
. An instance of theCharField
class, contains the text of the question.pub_date
. An instance of theDateTimeField
class, contains the publication date of the question.'date published'
is an optional first positional argument representing the human-readable name of the field.
The
Choice
model:question
. Association with aQuestion
.choice_text
. An instance of theCharField
class, contains the text of the choice.votes
. An instance of theIntegerField
class, contains the vote tally.
For more information about model fields, refer to the Django documentation.
To make Django aware of the new models, run the following command in the manage.py console:
The polls/migrations directory now contains the migration file 0001_initial.py:
Migrations are human-editable files, in which Django stores changes to data models. To apply changes and create tables in the database for the two new models, run the migrate
command again:
Performing administrative functions
Admin sites are used to add, edit, and otherwise manage the content. Django allows creating an admin site for your project automatically.
Setting up an admin site
Firstly, we need to create a superuser. To do that, type the
createsuperuser
command in the manage.py console, specify your email address, and password:Now go to
/admin/
on your Django server, for example, http://127.0.0.1:8000/admin/. You should see the following login 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 the admin that Question
objects have an admin interface.
Adding content
Open the file polls/admin.py, and type the following code:
from django.contrib import admin from .models import Question admin.site.register(Question)Refresh the page in the browser. The Polls section with Questions should appear:
Click Add to create a question:
When you a ready, click SAVE.
The newly created question appears in the list as Question object (1)
. Such naming makes content management complicated, as you have to open each question to see its text.
Let's fix it by adding a __str__()
method for both Question
and Choice
. Open polls/models.py and add the following lines:
You should end up with the following:
The list of questions now consists of human-readable names:
By design, each question must have a number of choices. However, choices are still not available in the admin interface. Let's fix that.
Providing features
Open the file polls/admin.py and edit it to get the folowing result:
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] admin.site.register(Question, QuestionAdmin)Now you can add choices to a question:
Creating Django templates
Until now, the design of the polls
application pages has been hardcoded in views. To make the application usable, you need to separate the visual representation of the output from the Python code. That can be done by using Django templates.
Open the file polls/views.py and replace its contents with the following code:
You can see unresolved references to the template files index.html, detail.html, and results.html:
PyCharm suggests a quick-fix: if you click the light bulb, or press Alt+Enter, you can choose to create the corresponding template file in the templates folder:
PyCharm also creates the directory polls where this template should reside. Confirm this operation:
By now, the file index.html is empty. Fill it with the following code:
The code generates the list of available questions, or displays "No polls are available" if there are none.
Pay attention to the icons and that appear in the gutter of the files views.py 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 in the articles Navigate between templates and views and Part 6. Django-specific navigation.
Now let's add the detail.html template file with the code that generates a page with a question text, radio buttons for choices, and a Vote button:
The results.html template will generate a page with voting results for all choices and a link for answering the same question again. Create the file and fill it with the following code:
Go to http://127.0.0.1:8000/polls/ in your browser and click the question link. You should see the following:
Select an option and click Vote. You will see a stub page with the "You are voting on question 1" message. That happens because we only have a dummy implementation of the vote()
function in /polls/views.py. Let's create a real one.
Open /polls/views.py and replace the vote()
function definition with the following one:
This key elements of the above code are:
request.POST['choice']
returns the ID of the selected choice.The
except
block is used to redisplay the question with an error message if no choice is provided.HttpResponseRedirect
redirects the user to a URL returned by thereverse()
function.The
reverse()
function is used to avoid hardcoding the URL. It accepts the name of the view that we want to pass control to and returns the URL of the voting results for the question.
Don't forget to update the import
statements in /polls/views.py as follows:
Now, if you go to http://127.0.0.1:8000/polls/ again and answer the question, you should see the following:
Here we are!
Now all features of our application work as designed. You can use the admin site to add as many questions as you like. While the Django server is running, you can access the list of questions at http://127.0.0.1:8000/polls/ and vote as many times as you like:
As you may have noticed, our app has a usability problem. When you click Vote again, it redirects you to the same question. A link to the list of all questions would be much more helpful. How do you fix that?
Check yourself
Open results.html.
Edit the last line to get the following:
<a href="{% url 'polls:index' %}">Vote again?</a>
Testing the application
Now let’s see how PyCharm helps simplify testing your application.
There is already the file tests.py in the polls directory. By now, this file is empty. Naturally, it is advisable to place the new tests in this particular file. For example, we'd like to make sure our poll is not empty:
To run this test, right-click the background of the file tests.py in the editor, choose the option Run, or just press Ctrl+Shift+F10. PyCharm suggests two options: to run UnitTest (which is defined as the default test runner), or a Django test.
The test results show in the Test Runner tab of the Run tool window:
Summary
This brief tutorial is over. You have successfully created and launched a simple Django application. Let's repeat what you managed to do with the help of PyCharm:
Created a Django project with an application
Launched a Django server
Configured a database
Created models, views and templates
Launched the application
Created and executed a test