Tutorials

Create a Django App in PyCharm

Read this post in other languages:

The core idea of Django is to let developers build their applications quickly. When you master this framework, the path from concept to production-ready web application will be a short one. However, if you want to go even faster, you can learn to create Django apps in PyCharm.

This tutorial will guide you through all of the steps to create a simple Django application that shows the current air temperature at your location. To bring in some interactivity, the app also lets you browse weather conditions at other random locations.

In this tutorial, you will learn how to:

  • Create a Django project in PyCharm.
  • Write models, views, and templates.
  • Make API calls and process responses.
  • Connect to databases and fill them with data.

To get the full application code, you can clone the repository. For information about cloning, see the PyCharm documentation.

Prerequisites

This tutorial is intended for developers who already have a few years’ experience with Python. Therefore, we assume that you have Python installed on your computer. If this is not the case, don’t worry! You can download and install your desired Python version when you start creating your first project in PyCharm.

As support for Django is a professional feature, you will need PyCharm Professional. There’s a free 30-day trial period for new users, and if you are a student or a teacher, you can apply for a free educational license. This tutorial was created in PyCharm 2023.1 with the new UI enabled.

For more information and installation instructions for different operating systems, please see the PyCharm documentation.

Kick-start your app

Let’s take our first steps. There aren’t many, and by the end, you will have the app running at the basic level.

Create a Django project in PyCharm

To create your project, launch PyCharm and click New Project. If PyCharm is already running, select File | New Project from the main menu.

In the New Project window that opens, specify the following:

Creating a Django project in PyCharm
  1. Choose Django as your project type.
  2. Type the name of the directory where your project will be located. This will also be used as your project name.
  3. Create a virtual environment for your new Django project where PyCharm will install your dependencies. For the purpose of this tutorial, we will select the virtualenv option.
  4. PyCharm lets you create a Django application within your project right away. Be sure to name the application here.

Click Create when you are ready. PyCharm creates the file structure, and installs Django and other required dependencies. 

Click the Run icon at the top of the window to start the Django server:

Running the Django server

The Run tool window will now open. Follow the link to open the browser window:

Django server page in the browser

It only took a couple of minutes to get a Django server running in PyCharm. That’s a good start, but the best things are still ahead.

Write your first view

It’s now time to start creating the application logic. In Django, that’s done by writing classes or functions in views.py.

You can explore the structure of your project at any time either by clicking the folder icon in the upper left corner of the PyCharm window or by pressing ⌘1 / Alt+1:

Accessing the Project tool window

This tutorial provides shortcuts that save a lot of time, such as pressing ⇧ (Shift) twice to open the Search Everywhere window. This shortcut lets you find literally anything, including your project files, settings, and actions.

Let’s use it to quickly open views.py.

Type views, move the cursor to views.py at meteo, and press Enter:

Using Search Everywhere

An editor tab with views.py will open. Let’s start with writing a temp_here function, which will return the current temperature at our location. 

Paste the following code in the editor:

import requests


def temp_here():
    location = geocoder.ip('me').latlng
    endpoint = "https://api.open-meteo.com/v1/forecast"
    api_request = f"{endpoint}?latitude={location[0]}&longitude={location[1]}&hourly=temperature_2m"
    return requests.get(api_request).json()

What’s happening here? First of all, we are importing the requests library which is required to make API calls. If there’s a red squiggly line in the import statement, it means that the package isn’t available in the selected Python interpreter.

Hover the cursor over it and select Install package requests.

Installing the requests library

To obtain the current temperature, temp_here makes a call to the Weather Forecast API. It’s a free API that doesn’t require an API key. All we need to know is the endpoint (https://api.open-meteo.com/v1/forecast) and the coordinates. For the latter, we’ll use Geocoder – a very simple Python library that lets you retrieve coordinates of various locations.

Place the caret over geocoder, which is highlighted with a red squiggly line, and press ⌥Enter / Alt+Enter to see the available quick fixes. Select Install and import package ‘geocoder’:

Installing and importing a Python package

PyCharm installs the package and adds the import statement to the beginning of the file.

What about making a test request to make sure that everything works as expected? The simplest way to do this is to invoke the function in the Python console. 

Let’s use another time saver – Find action. Instead of mousing through menus or memorizing dozens of shortcuts, just press ⇧⌘A / Ctrl+Shift+A and search for Run File in Python Console.

You don’t need to type out whole words. You can use a phrasing like 'rufipy' and still get the desired result:

As you run the command, PyCharm loads the imports and function definition into the console. Now, call temp_here. You can press Tab for code completion:

Using code completion in the Python console

Examine the API response from the console output. It’s a very long string, but you can find an illustrative representation below.

If you want to explore the response yourself, follow these steps:

  1. Click the console output 3 times and copy it to the clipboard by pressing ⌘C / Ctrl+C.
  2. Create a scratch file by pressing ⇧⌘N / Ctrl+Alt+Shift+Insert, and select the JSON file type (just start typing 'js…').
  3. Paste the response and apply the Reformat Code action. You can use Find action or press ⌥⌘L / Ctrl+Alt+L.

The required information is contained in the hourly element under the temperature_2m key. This key points to a list of values.

To get the current temperature, we must pass the current hour as the index. For example, if it’s 14:30 now, we’ll take the 14th item of the list.

Exploring the API response

Let’s check if temp_here()['hourly']['temperature_2m'][14] provides the required information.

Replace '14' according to your current time and type the code in the console:

Sending a request to the API from the Python console

14.9 °C is the current temperature at our location. What about yours?

Let’s modify the function so that it extracts the current temperature from the API response:

def temp_here():
    location = geocoder.ip('me').latlng
    endpoint = "https://api.open-meteo.com/v1/forecast"
    api_request = f"{endpoint}?latitude={location[0]}&longitude={location[1]}&hourly=temperature_2m"
    now = datetime.now()
    hour = now.hour
    meteo_data = requests.get(api_request).json()
    temp = meteo_data['hourly']['temperature_2m'][hour]
    return temp

Don’t forget to import datetime:

Click Rerun in the upper left corner of the Python console toolbar to reload the updated function definition, and then call temp_here again:

Calling the updated function from the Python console

If the result is different from the one you got before changing the code of the temp_here function, this could be because of a wrong TIME_ZONE value in settings.py

For more information, check out the Django documentation.

For quick access to this setting, press ⇧ (Shift) twice, switch to Symbols by pressing Tab a few times, and then start typing 'time…'.

Searching for a setting by using Search Everywhere

Let’s now turn temp_here into a view function. To be recognized by Django as a view, the function must accept an HttpRequest object as its first parameter, which is typically named request. It should also return an HttpResponse object.

Here’s what views.py should look like:

from datetime import datetime

import geocoder
import requests
from django.http import HttpResponse


def temp_here(request):
    location = geocoder.ip('me').latlng
    endpoint = "https://api.open-meteo.com/v1/forecast"
    api_request = f"{endpoint}?latitude={location[0]}&longitude={location[1]}&hourly=temperature_2m"
    now = datetime.now()
    hour = now.hour
    meteo_data = requests.get(api_request).json()
    temp = meteo_data['hourly']['temperature_2m'][hour]
    return HttpResponse(f"Here it's {temp}")

As you can see, we didn’t change much: temp_here now accepts request as an argument and returns HttpResponse with a string.

If you prefer to use Fahrenheit instead of Celsius, this is very easy to achieve by adding the temperature_unit parameter to the API request:

api_request = f"{endpoint}?latitude={location[0]}&longitude={location[1]}&hourly=temperature_2m&temperature_unit=fahrenheit"

If you prefer using Celsius, just skip this modification.

Configure URLs

To configure how our app will be accessed from the browser, update urls.py. Press Shift twice and type urls to find and open it as described above.

Add the following line to urlpatterns. You can use the Reformat Code action ⌥⌘L / Ctrl+Alt+L to easily restore the indents after pasting:

path("", include('meteo.urls')),

Don’t forget to import include from django.urls.include.

'meteo.urls' is now marked as an unresolved reference with a yellow squiggly line because the file doesn’t exist yet. That will be fixed in the following step.

Django projects often contain more than one app. Even if that’s not currently the case, consider the future development of the project. That’s why we create urls.py for each application in the corresponding folder and then include them all into the urls.py of the project.

So, let’s create urls.py in the folder of the meteo application.

Right-click the meteo directory in the Project tool window.

Select New > Python File and type urls.

The newly created file will open. Fill it with the following code:

from django.urls import path
from . import views


urlpatterns = [
    path('meteo/', views.temp_here, name='temp_here'),
]

When we now go to <server_address>/meteo in the browser, the temp_here function from views.py will be called, and the browser will render whatever the function returns.

It’s alive!

Rerun the Django server by clicking the Rerun button in the upper right corner and confirm the action:

Re-running the Django server

Open http://127.0.0.1:8000/meteo/ in your browser. You should see something similar to the following:

Application page in the browser

If you don’t want to open the browser and type the address, or refresh the page manually every time you restart the Django server, you can configure PyCharm to do that for you.

Open the drop-down list in the Run widget and select Edit configurations:

Editing the run configuration

Select your project’s configuration in the left pane, enable the Run browser checkbox, and add meteo to the url:

Configuring the URL

Click OK to apply the changes.

Technically, the app now works. But it doesn’t look nice in the browser, and still doesn’t have the “weather at random location” feature. In the following steps, we’ll introduce a template and import data to resolve these issues.

Improve the experience

Add a template

Let’s go back to views.py and modify the temp_here function again. If you’re still in meteo/urls.py, you can navigate there in no time. Hold / Ctrl, hover the mouse over temp_here, and click it when it turns into a hyperlink:

Navigating to the function definition

Start a new line before the return statement and type ‘template = loader’.

Press ⌥Enter/ Alt+Enter and use a quick-fix to import loader from django.template.loader:

Then, use get_template() to load index.html as a template:

    template = loader.get_template('index.html')

Now, replace the return statement with the following two lines:

    context = {'temp': temp}
    return HttpResponse(template.render(context, request))

Index.html is highlighted with a yellow squiggly line because it doesn’t exist yet. Hover the cursor over it and select Create template index.html.

Creating the template file

Click OK. PyCharm will create index.html and open it for editing.

The file is now empty. Let’s use a Live Template to fill it with template html code. Type html:5 and press Tab:

Using the live template

The visible content of an html page is located between the <body></body> tags. 

Insert the following code there:

<h1>Temperature at your location:</h1>
<h2>{{ temp }} &#8451;</h2>

Here, temp is a variable that is passed to the template from views. The names and values of variables should be saved into a dictionary and passed when rendering a template. That is what we’ve done by assigning {‘temp’ : temp} to the context variable in views.py above. 

The Unicode representation of the Celsius degrees symbol is &#8451. For Fahrenheit, use &#8457

Now, rerun the Django server to see the changes and make sure that the app works as expected. If you have edited the run configuration as explained above, the browser window should open automatically:

Application page generated from the template

Create a database and a model

To get temperature data for random locations from the API, we need to provide the coordinates of those locations.

Let’s use the World cities database by Juanma Hernández licensed under CC BY 4.0 for that purpose. Download the database and extract worldcities.csv from the archive. You’ll have to register at Kaggle, if you don’t already have an account there.

We also need to add the db.sqlite3 database, which was automatically created by Django, to our PyCharm project.

To do that:

  1. Open the Database tool window by clicking the database icon on the right. You can also access all tool windows by pressing ⌘E / Ctrl+E:
Accessing the Database tool window
  1. Click + in the upper-left corner of the tool window, and then select Data Source > SQLite. You can start typing 'sq…' to get to the required option faster:
Creating an SQL Lite data source
  1. Click next to the File field and browse for the db.sqlite3 file in your project folder.
  2. You may need to install, update, or switch the database driver. If there’s a warning at the bottom of the window, click the link to perform the required action:
Installing/switching the database driver
  1. Click OK.

To import data into the database, drag and drop worldcities.csv to db.sqlite3 in the Database tool window. In the dialog that opens, remove the unnecessary columns keeping only city, lat, lng, country, and id:

Now the db.sqlite3 database contains the worldcities table:

Worldcities table in the database structure

You can double-click it to view its content in the editor.

Django uses models to interact with databases. Let’s create a model to enable reading data from the worldcities table.

  1. Launch the manage.py task console by pressing ⌥R / Ctrl+Alt+R
  2. Type inspectdb worldcities and press Enter.
  3. Copy the Worldcities class from the console output to meteo\models.py.
  4. Replace null=True with primary_key=True for the id field.

Here’s what it should look like:

from django.db import models


class Worldcities(models.Model):
    city = models.TextField(blank=True, null=True)
    lat = models.FloatField(blank=True, null=True)
    lng = models.FloatField(blank=True, null=True)
    country = models.TextField(blank=True, null=True)
    id = models.IntegerField(blank=True, primary_key=True)

    class Meta:
        managed = False
        db_table = 'worldcities'

Add features

So far, we’ve had only one function (temp_here) in views.py which returns information about the current temperature at your location. Let’s add another function to show the temperature at a random location. It also needs to get the current temperature data from the API, so according to Python best practices, we should move that functionality to a separate function.

In PyCharm, that can be easily done with the help of the Extract method refactoring.

Select the lines that should be moved to a separate function and press ⌥⌘M / Ctrl+Alt+M. Alternatively, use Find Action:

Specify get_temp in the Method name field and click OK. We now have a get_temp function that accepts location as the sole parameter.

The temp_here function calls it to receive the temperature at the current location.

The result of Extract Method refactoring

Let’s create the temp_somewhere function. It should pass the coordinates of a random city to get_temp.

First, let’s do some prototyping in the Python console. Open it and paste the following code (if ImportError occurs, close and reopen the console):

from meteo.models import Worldcities
random_item = Worldcities.objects.all().order_by('?').first()

We need to obtain data from the worldcities table. As that is done by means of models, we import the Worldcities model from models.py.

Then, we randomize all objects with order_by(‘?’) and get the first object with first(). On the right side of the Python console tool window, there is the Variables tab. Expand the random_item node to check out the content of random_item:

Inspecting the variable in the Variables tab of the Python console

The complete code of the temp_somewhere function should look as follows:

def temp_somewhere(request):
    random_item = Worldcities.objects.all().order_by('?').first()
    city = random_item.city
    location = [random_item.lat, random_item.lng]
    temp = get_temp(location)
    template = loader.get_template("index.html")
    context = {
        'city': city,
        'temp': temp
    }
    return HttpResponse(template.render(context, request))

In addition to the temperature, context now contains the city name. Let’s edit the template so that it renders this information too.

You might have noticed the <> icon in the gutter. Click it to quickly switch to index.html:

Gutter icon for quick access to the template file

Replace the text between the <h1></h1> tags with {{ city }}:

Replacing the heading with a variable

Click the gutter icon for quick access to the temp_here function:

Gutter icon for quick access to the Python file

We need to modify it so that it also passes the city variable:

Updating the temp_here function

The temp_here function is called when the https://127.0.0.1/meteo page is opened in the browser, which we’ve configured in meteo/urls.py.

Let’s go back there and specify that temp_somewhere should be called when https://127.0.0.1/meteo/discover is accessed:

urlpatterns = [
    path('meteo/', views.temp_here, name='temp_here'),
    path('meteo/discover', views.temp_somewhere, name='temp_somewhere'),
]

Go back to index.html and add links to the /discover page and homepage. The latter will always show the temperature at the current location. Live templates and code completion save lots of time here:

To use live templates for paragraphs and links in html files, just type 'p' or 'a' respectively, and then press Tab.

To see the full list of available live templates, open settings ( / Ctrl+Alt+S), go to Editor > Live Templates, and then expand the Zen HTML node in the right pane:

Configuring the Live Templates settings

You can rerun the server and play around with the application:

Don’t stop

The app now works, but there’s room for improvement. The most obvious thing is its visual appearance, but extra features can also be added.

Use CSS

CSS is the fastest and simplest way to make your Django application look better. For example, you can use Simple.CSS.

Put the following line anywhere between the <head></head> tags in index.html:

<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">

Here’s the new look:

Applying CSS

Replacing links with buttons will also improve the look and feel:

Replacing links with buttons

To achieve this, replace the links between <p></p> tags in index.html with the following html code:

<div style="display: flex;">
    <form action="./discover">
        <input type="submit" value="Check other places"/>
    </form>
    &nbsp;
    <form action=".">
        <input style="background: #dc3545" type="submit" value="Home"/>
    </form>
</div>

You can see the results of editing index.html without switching from PyCharm to a browser. Hover the mouse over the upper-right corner of the editor window and select Built-in Preview:

Use Bootstrap

Bootstrap is a powerful and free frontend toolkit. To quickly apply it to your Django app, edit index.html as follows (for more information, see Bootstrap quick start guide):

  1. Add the link tag to the html head (replace the simple.css one from the previous steps):
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">

2. Add the code inside <body></body> tags with the following:

<div class="container text-center">
    <h1>{{ city }}</h1>
    <h2>{{ temp }} &#8451;</h2>
    <div class="btn-group" role="group">
        <button type="button" class="btn btn-outline-primary" onclick="location.href='./discover'">Check other places
        </button>
        <button type="button" class="btn btn-danger" onclick="location.href='.'">Home</button>
    </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>

Check out the result:

Using Bootstrap in the application

Bootstrap provides numerous ways of customizing the appearance of your apps. You can find all the necessary information in the documentation.

Check yourself

We’ve added the country field from the worldcities database to the Worldcities model, but didn’t use that data anywhere in the app. Now, you can test your skills by making the app show countries in addition to city names. As a result, you should get something similar to this:

Adding the country information to the application

Summary

In this tutorial, we’ve learned how to:

  • Create Django projects in PyCharm.
  • Write views and create templates.
  • Make API calls and process responses.
  • Connect databases and import data.
  • Improve the app’s visual appearance by applying CSS and Bootstrap.
image description