Professional Documents
Culture Documents
Weather Forcaste Django Project-3
Weather Forcaste Django Project-3
Django
Python
Django
Development
Introduction
In this article, you will build a Django app that displays the current weather for various
cities.
The current weather data will be provided by Open Weather Map API.
You will work with a database and create a form. What you learn in this tutorial can be
later applied to more complicated projects.
Prerequisites
This project will require Python installed, you should be able to refer to this tutorial
series for additional information.
The code in this article was written with Python 3 and Django 3.0, so to follow this
tutorial, you should be somewhat familiar with both.
You can start a virtual environment and run pip to install Django.
Or you can create a project directory, run pipenv, and then activate the pipenv shell.
Either method works, but for this article, you will be using pipenv.
Note: For alternative Django installation methods, you should be able to refer to this tutorial
series for additional information.
The official documentation provides instructions for installing pipenv with Homebrew or
Linuxbrew. It is also possible to install pipenv with pip.
1. mkdir the_weather_env
2.
Copy
1. cd the_weather_env
2.
Copy
This will install the latest version of Django for you. At the time of writing this article,
Django is on version 3.0.5.
Take this moment to also use pipenv to install the Requests library which you will be
using later:
1. pipenv install requests
2.
Copy
Activate the project’s virtualenv by running the following command in your Terminal:
1. pipenv shell
2.
Copy
Once you have Django installed, create and navigate to a directory for this project if you
haven’t already.
You can run the startproject command that Django gives you to generate the project.
Copy
Let’s try starting up your development server. To do that, navigate to the new directory,
in your Terminal:
(the_weather_env) cd the_weather
Copy
Next, use manage.py to run the runserver command in your Terminal:
Copy
If you check your Terminal, you should see the URL for your app. By default it should
be 127.0.0.1:8000:
al
If you are presented with a “Congratulations” page, you know you’ve set up Django correctly.
Step 3 — Logging into the Admin Dashboard
Next, you will log in to the admin dashboard Django gives you. To accomplish that, first,
you have to migrate your database, which means Django will create the pre-defined
tables that are needed for the default apps.
First, you need to stop the server. Depending on your environment this can be
accomplished with the keyboard command CONTROL+C or CTRL+C.
Next, run the migrate command in your Terminal:
1. python manage.py migrate
2.
Copy
By running that command, Django has created a SQLite database for you, the default
database in the settings, and it has added several tables to that database. You will
know if the database was created if you see a new db.sqlite3 file in your project
directory.
One of the tables Django gives you is a user table, which will be used to store any users
in your app. The app you are building does not need any users, but having an admin
user will allow you to access the admin dashboard.
To create an admin user, you’ll run the createsuperuser command in your Terminal:
1. python manage.py createsuperuser
2.
Copy
Follow the instructions by providing a username, email address, and password for your
admin user. Once you have finished, you will need to start the server again in your
Terminal:
If you log in with the username and password you just created, you will be presented
with the Django Admin Dashboard:
Groups and Users represent two models Django gives you access to. Models are just
code representations of tables in a database. Even though Django created more tables,
there is no need to access the rest of them directly, so no models were created.
If you click on ‘Users’ you should see more detail about the user table, and you should
see the user you created. Take a moment to explore by clicking different links in the
dashboard to see what is available. Just be careful not to delete your user, otherwise,
you will have to run createsuperuser again.
Let’s leave the admin dashboard for now and work on the code. You will need to create
an app inside of your project for your weather app.
urlpatterns = [
]
Copy
This file is similar to the urls.py in your the_weather directory. The difference is that
this urls.py file contains all the URLs that are relevant to the app itself.
You’re not specifying a URL yet, but you can set up the project to recognize your app
and route any URLs specific to your app to the app urls.py file.
First, go to the INSTALLED_APPS list in settings.py and add weather to the list:
the_weather/the_weather/settings.py
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'weather',
]
...
Copy
This lets Django know you want to use the weather app in your project. By doing this,
Django will know where to look for migrations and the URLs.
Next, you need to modify the original urls.py to point to your app urls.py file. To
accomplish that, you add a line under the existing path for the admin dashboard. You
also need to import include so you can point to your app urls.py file.
the_weather/the_weather/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('weather.urls')),
]
Copy
The empty string means that you do not need to use an endpoint for the entry point to
your app. Instead, you will let the app handle any specific endpoints. You could have
put something like path('weather/', ...), which would have meant you would have to
type 127.0.0.1:8000/weather/ to get anything associated with your weather app. But
since your project is simple, you won’t be doing that here.
Step 5 — Adding the Template and View
A template in Django is an HTML file that allows for extra syntax that makes the
template dynamic. You will be able to handle functionality like add
variables, if statements, and loops.
In your Terminal, navigate to the weather app directory:
1. cd weather
2.
Copy
Next, make the templates directory:
1. mkdir templates
2.
Copy
1. cd templates
2.
Copy
You will also create another directory with the same name as your app. This is because
Django combines all the template directories from the various apps you have. To
prevent filenames from being duplicated, you can use the name of your app to prevent
the duplicates:
1. mkdir weather
2.
Copy
Inside of this weather directory, create a new file called index.html. This will be your
main template.
Now that you have your template created, let’s create a view and URL combination so
you can actually see this in your app.
Views in Django are either functions or classes. In this case, since you’re creating a
simple view, you’ll create a function. Add this function to your views.py file:
the_weather/weather/views.py
from django.shortcuts import render
def index(request):
return render(request, 'weather/index.html') #returns the index.html template
Copy
You are naming your view index because it will be at the index of your app, which is the
root URL. To have the template render, you return request, which is necessary for
the render function, and the name of the template file you want to render, in this
case, weather/index.html.
Let’s add the URL that will send the request to this view. In the urls.py file for the app,
update the urlpatterns list.
the_weather/weather/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index), #the path for our index view
]
Copy
Django is going to match any URL without an endpoint and route it to the view function
you created.
Copy
Then, open your web browser and visit 127.0.0.1:8000 again:
You will observe the rendered HTML of the index.html file. There is an input to
add a city. And there is a display of the hardcoded weather for Las Vegas. However, the form at
this point does not work and the weather is just a placeholder. Let’s work on that next.
Step 6 — Using the Weather API
What you want to do now is sign up for the Open Weather Map API. This will allow you
to get real-time weather for any cities that you add to your app.
Go to the site, create an account and then go to the API keys on their dashboard. You
can use the Default key that they provide or you can create a new API key. This key will
allow you to use the API to get the weather.
Note: It is important to keep API keys secret to prevent them from being used by other
parties. You will want to avoid committing your API keys to remote repositories like GitHub.
The one endpoint you will use is below, so you can see the data that gets returned by
modifying the following URL with your API key and navigating to the URL in your
browser:
http://api.openweathermap.org/data/2.5/weather?q=las%20vegas&units=imperial&appid
=YOUR_APP_KEY
It may take a few minutes for your API key to become active, so if it does not work at
first, try again after a few minutes.
You should see a response in JSON format with coordinates, temperatures, and
weather conditions.
With that, let’s add in a request to get the data into your app.
Let’s update your index view to send a request to the URL you have.
the_weather/weather/views.py
from django.shortcuts import render
import requests
def index(request):
url =
'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_AP
P_KEY'
With those new lines, you’re adding the URL that you will send a request to.
Note that this URL is slightly different from the URL you tested earlier in the browser.
The city is not part of the URL, it has been moved out to a variable. This pattern will
allow you to substitute other city names in the future.
For now, you will set the city to be “Las Vegas”, but later this will be set to the cities from
the database.
Finally, you will send the request to the URL using the city and get the JSON
representation of that city.
If you print that to the console you can see the same data you saw when you put the
URL in your address bar:
the_weather/weather/views.py
...
def index(request):
...
print(city_weather) #temporarily view output
If you reload the page in your web browser, you will see the data get printed to your
console.
After this is verified to be true, you can remove the print statement from your code.
Step 7 — Displaying the Data in the Template
Next, you will need to pass the data to the template so it can be displayed to the user.
Let’s create a dictionary to hold all of the data you need. Of the data returned, you will
need temp, description, and icon.
the_weather/weather/views.py
...
def index(request):
...
weather = {
'city' : city,
'temperature' : city_weather['main']['temp'],
'description' : city_weather['weather'][0]['description'],
'icon' : city_weather['weather'][0]['icon']
}
Copy
With the weather data added inside of context, let’s go to the template to add the data.
Inside of the index.html template, all you need to do is modify the HTML to use
variables instead of the hard-coded values. Variables will use {{ }} tags, and they will
reference anything inside of your context dictionary.
Note that Django converts dictionary keys so you can only access them using dot
notation. For example, weather.city will give you the city name. You do not
use weather['city'] like you would in Python.
Find the “box” <div>, and update it to use variables:
the_weather/weather/templates/weather/index.html
...
<div class="box">
<article class="media">
<div class="media-left">
<figure class="image is-50x50">
<img src="http://openweathermap.org/img/w/{{ weather.icon }}.png"
alt="Image">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<span class="title">{{ weather.city }}</span>
<br>
<span class="subtitle">{{ weather.temperature }}° F</span>
<br> {{ weather.description }}
</p>
</div>
</div>
</article>
</div>
...
Copy
With all the variables replaced, you will now be presented with the current weather for
your city.
However, the city is still currently hardcoded. What you will want to do next is pull from
the database and display the cities that are in your database.
To accomplish that, you will create a table in your database to hold the cities that you
want to know the weather for. You will create a model for this.
Go to the models.py file in your weather app, and add the following:
the_weather/weather/models.py
from django.db import models
class City(models.Model):
name = models.CharField(max_length=25)
Let’s stop the server and then perform the migrations in your Terminal:
1. python manage.py makemigrations
2.
Copy
And migrate:
1. python manage.py migrate
2.
Copy
You need to make it possible to see this model on your admin dashboard. To
accomplish that, you will need to register it in your admin.py file.
the_weather/weather/admin.py
from django.contrib import admin
from .models import City
admin.site.register(City)
Copy
Next, restart the server and view the admin dashboard in your web browser.
City is now an option.
You can then go into the admin dashboard and add some cities. For example: “London”,
“Tokyo”, and “Las Vegas”.
With the entries in the database, you will need to query these entries in your view. Start
by importing the City model and then querying that model for all objects:
the_weather/weather/views.py
from django.shortcuts import render
import requests
from .models import City
Copy
Then, update the request with cities:
the_weather/weather/views.py
...
def index(request):
url =
'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_AP
P_KEY'
Since you have the list of cities, you will want to loop over them and get the weather for
each one and add it to a list that will eventually be passed to the template.
This will just be a variation of what you did in an earlier step. The difference is you are
looping and appending each dictionary to a list.
First, you will create a weather_data list to hold the weather for each city.
Then, replace the original city variable and with a loop over cities.
Next, the weather response for each city should be appended to weather_data.
You will also need to update the context to pass this list instead of a single dictionary.
At this point, your views.py should resemble:
the_weather/weather/views.py
...
def index(request):
...
cities = City.objects.all() #return all the cities in the database
weather_data = []
weather = {
'city' : city,
'temperature' : city_weather['main']['temp'],
'description' : city_weather['weather'][0]['description'],
'icon' : city_weather['weather'][0]['icon']
}
weather_data.append(weather) #add the data for the current city into our
list
Now, you can examine the data for all the cities you have in the database.
The last step is allowing the user to add a city directly via the form.
To accomplish that, you will need to create a form. You could create the form manually,
but since your form will have exactly the same field as your model, you can use
a ModelForm.
Create a new file called forms.py in your weather app:
the_weather/weather/forms.py
from django.forms import ModelForm, TextInput
from .models import City
class CityForm(ModelForm):
class Meta:
model = City
fields = ['name']
widgets = {
'name': TextInput(attrs={'class' : 'input', 'placeholder' : 'City
Name'}),
} #updates the input class to have the correct Bulma class and
placeholder
Copy
To display the form, you will need to create it in your view and pass it to the template.
To accomplish that, let’s update the index.html to create the form. You will also need to
update the context so the form gets passed to the template.
the_weather/weather/views.py
...
from .forms import CityForm
def index(request):
...
form = CityForm()
weather_data = []
...
context = {'weather_data' : weather_data, 'form' : form}
Copy
Now in the index.html template, let’s update the form section to use the form from your
view and a csrf_token, which is necessary for POST requests in Django.
the_weather/weather/templates/weather/index.html
...
<form method="POST">
{% csrf_token %}
<div class="field has-addons">
<div class="control is-expanded">
{{ form.name }}
</div>
<div class="control">
<button class="button is-info">
Add City
</button>
</div>
</div>
</form>
...
Copy
Note: CSRF stands for Cross-Site Request Forgery. This is a security measure to ensure
form data is being submitted from an expected trusted source.
With the form in your HTML working, you will need to handle the form data as it comes
in. For that, you will create an if block checking for a POST request. You need to add
the check for the type of request before you start grabbing the weather data so you
immediately get the data for the city you add.
the_weather/weather/views.py
...
def index(request):
url =
'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_AP
P_KEY'
form = CityForm()
...
Copy
By passing request.POST, you will be able to validate the form data.
Now, you should be able to type in the name of a city, click add, and see it show up.
You now have a way to keep track of the weather for multiple cities in your app.
Conclusion
In this article, you had to work with various parts of Django to get this working: views,
models, forms, and templates. You also had to use the Python library requests to get
the actual weather data. So even though the app is simple, you will use many of the
same concepts in apps with more complexity.