django中的app_在Django中构建Weather App

django中的app

In this article we'll build a simple Django app that displays the current weather for various cities. To get the current weather data, we'll use the Open Weather Map API.

在本文中,我们将构建一个简单的Django应用,以显示各个城市的当前天气。 要获取当前的天气数据,我们将使用Open Weather Map API

Even though the app is simple, we'll work with a database and create a form, so the concepts used here are applicable to more complicated projects.

即使该应用程序很简单,我们仍将使用数据库并创建表单,因此此处使用的概念适用于更复杂的项目。

The code in this article was written with Python 3 and Django 2.0, so to follow this tutorial, you should be somewhat familiar with both. If you'd like an introduction to both, check out our article called Build Your First Python and Django Application. That article uses Django 1.X, but you'll see the only difference is in how URLs are defined.

本文中的代码是使用Python 3和Django 2.0编写的,因此,要熟悉本教程,您应该对两者都有些熟悉。 如果您想同时介绍这两者,请查看我们的文章Build Your First Python and Django Application 。 该文章使用的是Django 1.X,但您将看到的唯一区别是URL的定义方式。

Here's what our app is going to look like when we're done.

这是我们的应用程序完成后的外观。

App we're building

You can see a live demo of the app on Python Anywhere.

您可以在Python Anywhere上看到该应用程序的实时演示。

All the code for this article is on GitHub.

本文的所有代码都在GitHub上

If you'd like to see a video of me building this app, check out this YouTube video: https://youtu.be/v7xjdXWZafY

如果您想观看有关我在构建此应用程序的视频,请查看以下YouTube视频: https : //youtu.be/v7xjdXWZafY

安装 ( Installation )

Installing Django is like installing any other Python library: you can start a virtual environment and run pip to install Django, or you can do what I do and create a project directory, run pipenv and then activate the pipenv shell. Either method works, but for this article I'll be using pipenv.

安装Django就像安装其他Python库一样:您可以启动虚拟环境并运行pip来安装Django,或者可以执行我的操作并创建项目目录,运行pipenv,然后激活pipenv shell。 两种方法都可以,但是对于本文,我将使用pipenv。

pipenvinstall django

This will install the latest version of Django for you. At the time of writing this article, Django is on version 2.0.4.

这将为您安装最新版本的Django。 在撰写本文时,Django的版本为2.0.4。

Once you have Django installed, create and navigate to a directory for this project if you haven't already. Once there, you can run the startproject command that Django gives you to generate the project.

安装Django之后,请创建并导航至该项目的目录(如果尚未安装)。 到达那里后,您可以运行Django提供的startproject命令来生成项目。

django-admin startproject the_weather

Django should have created a few new files in your directory.

Django应该在您的目录中创建了一些新文件。

Let's try starting up our development server. To do that, navigate to the new directory and use manage.py to run the runserver command in your terminal:

让我们尝试启动我们的开发服务器。 为此,请导航到新目录并使用manage.py在终端中运行runserver命令:

cd the_weather
python manage.py runserver

If you look at your terminal, you should see the URL for your app. By default it should be 127.0.0.1:8000.

如果您查看终端,应该会看到应用程序的URL。 默认情况下,它应该是127.0.0.1:8000。

First start

Open up your browser and go to that URL.

打开浏览器,然后转到该URL。

Congrats Page

If you see that, you know you've set up Django correctly. You definitely should see it because we haven't even tried modifying the code yet.

如果看到该信息,说明您已正确设置了Django。 您绝对应该看到它,因为我们还没有尝试修改代码。

管理员控制台 ( The Admin Dashboard )

Next we want to take a look at the admin dashboard Django gives us. To do that, first we have to migrate our database, which means Django will create the pre-defined tables that are needed for the default apps. To do this, you simply run the migrate command. Stop the server by using CTRL+C and then run:

接下来,我们要看看Django给我们的管理仪表板。 为此,首先我们必须迁移数据库,这意味着Django将创建默认应用所需的预定义表。 为此,您只需运行migration命令。 通过使用CTRL + C停止服务器,然后运行:

python manage.py migrate

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'll know if the database was created if you see a new db.sqlite3 file in your project directory.

通过运行该命令,Django为您创建了SQLite数据库,这是设置中的默认数据库,并且已向该数据库添加了多个表。 你要知道,如果你看到一个新的数据库创建了数据库。 项目目录中的sqlite3文件。

One of the tables Django gives us is a user table, which will be used to store any users in our app. The app we're building doesn't need any users, but having an admin user will allow us to access the admin dashboard.

Django提供给我们的表之一是用户表,该表将用于存储应用程序中的所有用户。 我们正在构建的应用程序不需要任何用户,但是拥有管理员用户将使我们能够访问管理仪表板。

To create an admin user, we'll run the createsuperuser command.

要创建管理员用户,我们将运行createsuperuser命令。

python manage.py createsuperuser

Follow the instructions by giving a username, email address, and a password for your admin user. Once you've done that, you'll need to start the server again and navigate to the admin dashboard.

按照说明进行操作,并为您的管理员用户提供用户名,电子邮件地址和密码。 完成此操作后,您需要再次启动服务器并导航到管理仪表板。

python manage.py runserver

Then go to 127.0.0.1:8000/admin.

然后转到127.0.0.1:8000/admin。

The reason why we can go to this page is because because admin is set up in our urls.py (the reason why we can see the congratulations page is because Django gives you that until you add your own URLs).

之所以可以转到此页面,是因为在urls.py中设置了admin(我们可以看到祝贺页面的原因是Django在您添加自己的URL之前为您提供了此功能)。

If you login with the username and password you just created, you should see this page.

如果使用刚创建的用户名和密码登录,则应该看到此页面。

Admin Dashboard

Groups and users represent two models Django gives us access to. Models are just code representations of tables in a database. Even though Django created more tables, there's no need to access the rest of them directly, so no models were created.

组和用户代表Django允许我们访问的两个模型。 模型只是数据库中表的代码表示。 即使Django创建了更多表,也无需直接访问其余表,因此不会创建任何模型。

If you click on 'user' you should see more detail about the user table, and you should see the user you created. I recommend clicking different links in the dashboard to see what's there. Just be careful not to delete your user, otherwise you'll have to run createsuperuser again.

如果单击“用户”,则应该看到有关用户表的更多详细信息,并且还应该看到创建的用户。 我建议单击仪表板上的其他链接以查看其中的内容。 请注意不要删除用户,否则,您将不得不再次运行createsuperuser。

Let's leave the admin dashboard for now and go to the code. We need to create an app inside of our project for our weather app.

现在让我们离开管理仪表板,转到代码。 我们需要在项目内部为天气应用程序创建一个应用程序。

创建应用 ( Creating the App )

In Django, you can separate functionality in your project by using apps. I think app is a confusing name because we usually refer to an app as being the entire project, but in the case of Django, app refers to a specific piece of functionality in your project. For example, if you look at the settings.py file, you'll see the INSTALLED_APPS list.

在Django中,您可以使用应用来分离项目中的功能。 我认为应用程序是一个令人困惑的名称,因为我们通常将应用程序称为整个项目,但就Django而言,应用程序指的是项目中的特定功能。 例如,如果查看settings.py文件,则会看到INSTALLED_APPS列表。

The first of the installed apps, django.contrib.admin is what we just used. It handles all the admin functionality and nothing else. Another app in our project by default are things like auth, which allowed us to log into our admin dashboard.

我们刚刚使用的是已安装的第一个应用程序django.contrib.admin。 它处理所有管理功能,仅此而已。 默认情况下,项目中的另一个应用程序是auth之类的东西,它使我们能够登录到管理仪表板。

In our case, we need to create a new app to handle everything related to showing the weather. To create that app, stop the server with CTRL+C and run:

就我们而言,我们需要创建一个新的应用程序来处理与显示天气有关的所有事情。 要创建该应用,请使用CTRL + C停止服务器并运行:

python manage.py startapp weather

By running startapp, Django has added a new directory and more files to our project.

通过运行startapp,Django为我们的项目添加了一个新目录和更多文件。

With the latest files generated, let's create a new file called urls.py in our app directory.

生成最新文件后,让我们在应用目录中创建一个名为urls.py的新文件。

#the_weather/weather/urls.py

from django.urls import path

urlpatterns = [
]

This file is similar to the urls.py in our the_weather directory. The difference is that this urls.py file contains all the URLs that are relevant to the app itself.

该文件类似于我们的theweather目录中的urls.py。 不同之处在于此urls.py文件包含与应用程序本身相关的所有URL。

We're not specifying a URL yet, but we can set up the project to recognize our app and route any URLs specific to our app to the app urls.py file.

我们尚未指定URL,但是我们可以设置项目以识别我们的应用程序并将特定于我们应用程序的所有URL路由到应用程序urls.py文件。

First, go to the INSTALLED_APPS list and add this app to the list.

首先,转到INSTALLED_APPS列表,然后将此应用添加到列表中。

#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',
]

...

This lets Django know we want to use the weather app in our project. By doing this, Django will know where to look for migrations and the URLs.

这使Django知道我们要在项目中使用weather应用程序。 这样,Django将知道在何处查找迁移和URL。

Next, we need to modify the original urls.py to point to our app urls.py file. To do that, we add a line under the existing path for the admin dashboard. We also need to import 'include' so we can point to our app urls.py file.

接下来,我们需要修改原始的urls.py以指向我们的应用程序urls.py文件。 为此,我们在管理控制台的现有路径下添加一行。 我们还需要导入“ include”,以便可以指向我们的应用程序urls.py文件。

#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')),
]

The empty string means that we won't use an endpoint for the entry point to our app. Instead we'll let the app handle any specific endpoints. We could have easily put something like path('weather/', ...), which would have meant we would have to type 127.0.0.1:8000/weather/ to get anything associated with our weather app. But since our project is simple, we won't be doing that here.

空字符串表示我们不会将端点用作应用程序的入口点。 相反,我们将让该应用处理任何特定的端点。 我们可以很容易地输入path('weather /',...)之类的东西,这意味着我们必须输入127.0.0.1:8000/weather/才能获取与我们的天气应用程序相关的任何内容。 但是由于我们的项目很简单,因此我们在这里不会这样做。

添加模板和视图 ( Adding the Template and View )

Now for the first interesting thing we're going to do. We need to add the template to our project.

现在,我们要做的第一件事是有趣的。 我们需要将模板添加到我们的项目中。

A template in Django is just an HTML file that allows for extra syntax that makes the template dynamic. We'll be able to do things like add variables, if statements, and loops, among other things.

Django中的模板只是一个HTML文件,它允许使模板动态化的额外语法。 我们将能够做诸如添加变量,if语句和循环之类的事情。

To start, I have an HTML file that's free any template syntax, but this will be enough for us to start.

首先,我有一个免费HTML文件,该文件不包含任何模板语法,但这足以让我们开始。

We're going to create a template directory to put this file in.

我们将创建一个模板目录来放置该文件。

cd weather
mkdir templates && cd templates
mkdir weather

We also created another directory with the same name as our app. We did this because Django combines all the templates directories from the various apps we have. To prevent filenames being duplicated, we can use the name of our app to prevent the duplicates.

我们还创建了另一个名称与应用程序相同的目录。 我们之所以这样做,是因为Django结合了我们拥有的各种应用程序中的所有模板目录。 为了防止文件名重复,我们可以使用应用程序的名称来防止重复。

Inside of the weather directory, create a new file called index.html. This will be our main template. Here's the HTML we'll use for the template.

在weather目录中,创建一个名为index.html的新文件。 这将是我们的主要模板。 这是我们将用于模板HTML。

<!-- the_weather/weather/templates/weather/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>What's the weather like?</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css" />
</head>
<body>
    <section class="hero is-primary">
        <div class="hero-body">
            <div class="container">
                <h1 class="title">
                    What's the weather like?
                </h1>
            </div>
        </div>
    </section>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-offset-4 is-4">
                    <form method="POST">
                        <div class="field has-addons">
                            <div class="control is-expanded">
                                <input class="input" type="text" placeholder="City Name">
                            </div>
                            <div class="control">
                                <button class="button is-info">
                                    Add City
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-offset-4 is-4">
                    <div class="box">
                        <article class="media">
                            <div class="media-left">
                                <figure class="image is-50x50">
                                    <img src="http://openweathermap.org/img/w/10d.png" alt="Image">
                                </figure>
                            </div>
                            <div class="media-content">
                                <div class="content">
                                    <p>
                                        <span class="title">Las Vegas</span>
                                        <br>
                                        <span class="subtitle">29° F</span>
                                        <br> thunderstorm with heavy rain
                                    </p>
                                </div>
                            </div>
                        </article>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <footer class="footer">
    </footer>
</body>
</html>

Now that we have our template created, let's create a view and URL combination so we can actually see this in our app.

现在我们已经创建了模板,让我们创建一个视图和URL组合,以便我们实际上可以在我们的应用程序中看到它。

Views in Django are either functions or classes. In our case since we're creating a simple view, we'll create a function. Add this function to your views.py:

Django中的视图是函数或类。 就我们而言,由于我们正在创建一个简单的视图,因此我们将创建一个函数。 将此功能添加到您的views.py:

#the_weather/weather/views.py

from django.shortcuts import render

def index(request):
    return render(request, 'weather/index.html') #returns the index.html template

We're naming our view 'index' because it will be at the index of our app, which is the root URL. To have the template render, we return request, which is necessary for the render function, and the name of the template file we want to render, in this case weather/index.html.

我们正在命名视图“索引”,因为它将位于应用程序的索引(即根URL)处。 要渲染模板,我们返回渲染功能所必需的请求,以及我们要渲染的模板文件的名称,在本例中为weather / index.html。

Let's add the URL that will send the request to this view. In the urls.py for the app, update the urlpatterns list.

让我们添加将请求发送到该视图的URL。 在网址中py for app,更新urlpatterns列表。

#the_weather/weather/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),  #the path for our index view
]

This allows us to reference the view we just created.

这使我们可以引用刚刚创建的视图。

Django is going to match any URL without an endpoint and route it to the view function we created.

Django将匹配任何没有端点的URL,并将其路由到我们创建的view函数。

Go back to your project root, start the server, and go to 127.0.0.1:8000 again.

返回项目根目录,启动服务器,然后再次转到127.0.0.1:8000。

python manage.py runserver

Template returned

What we see now is just the result of the HTML you have in index.html file. You'll see an input to add a city and the weather for Las Vegas. However, the form doesn't work and the weather is just a placeholder, but don't worry, because we'll be creating those for this app.

我们现在看到的只是index.html文件中HTML的结果。 您会看到一个输入,用于添加拉斯维加斯的城市和天气。 但是,该表单不起作用,天气只是一个占位符,但请不要担心,因为我们将为此应用程序创建这些占位符。

使用天气API ( Using the Weather API )

What we want to do now is sign up for the Open Weather Map API. This will allow us to get the actual weather for any cities that we add in our app.

我们现在要做的是注册Open Weather Map API 。 这将使我们能够获取应用程序中添加的任何城市的实际天气。

Go to the site, create an account and then go to the API keys on their dashboard. Enter a name and generate a new API key. This key will allow us to use the API to get the weather.

转到该站点,创建一个帐户,然后转到其仪表板上的API密钥。 输入名称并生成新的API密钥。 此密钥将使我们能够使用API​​来获取天气。

Open Weather Map Dashboard

The one endpoint we'll use is below, so you can see the actual data that gets returned by modifying the following URL with your API key and navigating to the URL in your browser. It may take a few minutes for your API key to become active, so if it doesn't work at first, try again in after a few minutes.

我们将使用的一个端点在下面,因此您可以通过使用API​​密钥修改以下URL并导航至浏览器中的URL来查看返回的实际数据。 您的API密钥可能需要几分钟的时间才能激活,因此,如果一开始不起作用,请在几分钟后重试。

http://api.openweathermap.org/data/2.5/weather?q=las%20vegas&units=imperial&appid=YOUR_APP_KEY

With that, let's add in a request to get the data into our app.

这样,让我们​​添加一个请求以将数据导入我们的应用程序。

First, we'll need to install requests so we can call the API from inside our app.

首先,我们需要安装请求,以便我们可以从应用程序内部调用API。

pipenvinstall requests

Let's update our index view to send a request to the URL we have.

让我们更新索引视图,以将请求发送到我们拥有的URL。

#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_APP_KEY'
    city = 'Las Vegas'
    city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types

    return render(request, 'weather/index.html') #returns the index.html template

With those three lines, we're adding the URL that will send a request to. We'll make the part for the city a placeholder for when we allow users to add their own cities.

在这三行代码中,我们添加了向其发送请求的URL。 当我们允许用户添加自己的城市时,我们将为城市提供占位符。

For now we'll set the city to be Las Vegas, but later this will be set to the cities from the database.

现在,我们将城市设置为拉斯维加斯,但是稍后将其从数据库中设置为城市。

Finally, we'll send the request to the URL using the city and get the JSON representation of that city. If we print that to the console we can see the same data we saw when we put the URL in our address bar.

最后,我们将使用城市将请求发送到URL,并获取该城市的JSON表示形式。 如果将其打印到控制台,则可以看到与将URL放入地址栏中时看到的相同数据。

If you start your server again and reload the page, you'll see the data get printed to your console.

如果再次启动服务器并重新加载页面,则会看到数据已打印到控制台。

API Data

在模板中显示数据 ( Displaying the Data in the Template )

Next, we 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 we need. Of the data returned to us, we 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']
    }

    return render(request, 'weather/index.html') #returns the index.html template

Now that we all the information we want, we can pass that to the template. To pass it to the template, we'll create a variable called context. This will be a dictionary that allows us to use its values inside of the template.

现在我们有了所需的所有信息,我们可以将其传递给模板。 要将其传递给模板,我们将创建一个名为context的变量。 这将是一个字典,允许我们在模板内部使用其值。

#the_weather/weather/views.py

def index(request):
    ...
    context = {'weather' : weather}
    return render(request, 'weather/index.html', context) #returns the index.html template

And then in render, we'll add the context as the third argument.

然后在渲染中,我们将上下文添加为第三个参数。

With the weather data added inside of context, let's go to the template to add the data.

将天气数据添加到上下文中后,让我们转到模板以添加数据。

Inside of the template, all we need to do is modify the HTML to use variables instead of the values I typed in. Variables will use {{ }} tags, and they will reference anything inside of your context dictionary.

在模板内部,我们所需要做的就是修改HTML以使用变量而不是我键入的值。变量将使用{{}}标签,并且它们将引用上下文字典中的所有内容。

Note that Django converts dictionary keys so you can only access them using dot notation. For example, weather.city will give us the city name. We don't use weather['city'] like we would in Python.

请注意,Django会转换字典键,因此您只能使用点表示法来访问它们。 例如,weather.city将为我们提供城市名称。 我们不像在Python中那样使用weather ['city']。

Find the box div, and update it to this:

找到div框,并将其更新为:

<!-- 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>

With all the variables replaced, we should now see the current weather for our city.

替换所有变量后,我们现在应该可以看到城市的当前天气。

Weather for Las Vegas

Great! Now we can see the weather for one city, but we had to hard code the city. What we want to do now is pull from the database and show the cities that are in our database.

大! 现在我们可以看到一个城市的天气,但是我们必须对该城市进行硬编码。 我们现在要做的是从数据库中提取并显示数据库中的城市。

To do that, we'll create a table in our database to hold the cities that we want to know the weather for. We'll create a model for this.

为此,我们将在数据库中创建一个表,以保存我们想知道天气的城市。 我们将为此创建一个模型。

Go to the models.py in your weather app, and add the following:

在您的天气应用中转到models.py,然后添加以下内容:

#the_weather/weather/models.py

from django.db import models

class City(models.Model):
    name = models.CharField(max_length=25)

    def _str_(self): #show the actual city name on the dashboard
        return self.name

    class Meta: #show the plural of city as cities instead of citys
        verbose_name_plural = 'cities'

This will create a table in our database that will have a column called name, which is the name of the city. This city will be a charfield, which is just a string.

这将在我们的数据库中创建一个表,该表具有名为name的列,这是城市的名称。 这个城市将是一个charfield,只是一个字符串。

To get these changes in the database, we have to run makemigrations to generate the code to update the database and migrate to apply those changes. So let's do that now.

为了在数据库中获得这些更改,我们必须运行makemigrations生成代码以更新数据库并进行迁移以应用这些更改。 所以现在就开始做。

python manage.py makemigrations
python manage.py migrate

We need to make it to where we can see this model on our admin dashboard. To do that, we need to register it in our admin.py file.

我们需要使其在管理仪表板上可以看到该模型的地方。 为此,我们需要在admin.py文件中注册它。

#the_weather/weather/admin.py

from django.contrib import admin
from .models import City

admin.site.register(City)

You'll see the city as an option on the admin dashboard.

您会在管理控制台上看到城市作为选项。

Cities on Admin Dashboard

We can then go into the admin dashboard and add some cities. I'll start with three: London, Tokyo, and Las Vegas.

然后,我们可以进入管理仪表板并添加一些城市。 我将从三个方面开始:伦敦,东京和拉斯维加斯。

Three cities weather

With the entries in the database, we need to query these entries in our 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
#the_weather/weather/views.py

def index(request):
    url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'
    cities = City.objects.all() #return all the cities in the database
    ...

Since we have the list of cities, we 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 a variation of what we did in the first case. The other difference is we are looping and appending each dictionary to a list. We'll remove the original city variable in favor a city variable in the loop.

这只是我们在第一种情况下所做的一种变体。 另一个区别是我们正在循环并将每个字典追加到列表中。 我们将删除原始的city变量,以便在循环中使用city变量。

#the_weather/weather/views.py

def index(request):
    ...
    weather_data = []

    for city in cities:

        city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types

        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

    context = {'weather_data' : weather_data}
    ...

Cool, so we have the data. Now let's update the context to pass this list instead of a single dictionary.

很酷,所以我们有数据。 现在,让我们更新上下文以传递此列表,而不是单个字典。

#the_weather/weather/views.py

    ...
    context = {'weather_data' : weather_data}
    ...

Next, inside of the template, we need to loop over this list and generate the HTML for each city in the list. To do this, we can put a for loop around the HTML that generates a single box for the city.

接下来,在模板内部,我们需要遍历此列表并为列表中的每个城市生成HTML。 为此,我们可以在HTML周围放置一个for循环,以为城市生成一个框。

<!-- the_weather/weather/index.html -->
<div class="column is-offset-4 is-4">
    {% for weather in weather_data %}
    <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>
    {% endfor %}
</div>

Awesome! Now we can see the data for all the cities we have in the database.

太棒了! 现在,我们可以查看数据库中所有城市的数据。

创建表格 ( Creating the Form )

The last thing we want to do is allow the user to add a city directly in the form.

我们要做的最后一件事是允许用户直接在表单中添加城市。

To do that, we need to create a form. We could create the form directly, but since our form will have exactly the same field as our model, we can use a ModelForm.

为此,我们需要创建一个表单。 我们可以直接创建表单,但是由于表单将具有与模型完全相同的字段,因此我们可以使用ModelForm。

Create a new file called forms.py.

创建一个名为forms.py的新文件。

#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

To view the form, we need to create it in our view and pass it to the template.

要查看表单,我们需要在视图中创建表单并将其传递给模板。

To do that, let's update the index video to create the form. We'll replace the old city variable at the same time since we no longer need it. We also need to update the context so the form gets passed to the template.

为此,让我们更新索引视频以创建表单。 由于我们不再需要它,因此我们将同时替换旧的城市变量。 我们还需要更新上下文,以便将表单传递给模板。

#the_weather/weather/views.py

def index(request):
    ...
    form = CityForm()

    weather_data = []
    ...
    context = {'weather_data' : weather_data, 'form' : form}

Now in the template, let's update the form section to use the form from our view and a csrf_token, which is necessary for POST requests in Django.

现在在模板中,让我们更新表单部分以使用我们视图中的表单和csrf_token,这对于Django中的POST请求是必需的。

<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>

With the form in our HTML working, we now need to handle the form data as it comes in. For that, we'll create an if block checking for a POST request. We need to add the check for the type of request before we start grabbing the weather data so we immediately get the data for the city we add.

在HTML中的表单正常工作后,我们现在需要处理表单数据,因为它要传入。为此,我们将为POST请求创建if块检查。 在开始获取天气数据之前,我们需要添加请求类型的检查,以便我们立即获取所添加城市的数据。

#the_weather/weather/views.py

def index(request):
    cities = City.objects.all() #return all the cities in the database

    url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'

    if request.method == 'POST': # only true if form is submitted
        form = CityForm(request.POST) # add actual request data to form for processing
        form.save() # will validate and save if validate

    form = CityForm()
    ...

By passing request.POST, we'll be able to validate the form data.

通过传递request.POST,我们将能够验证表单数据。

Now you should be able to type in the name of a city, click add, and see it show up. I'll add Miami as the next city.

现在,您应该能够输入城市的名称,单击添加,然后看到它出现。 我将迈阿密作为下一个城市。

Form submitted with new city

When we drop out of the if block, the form will be recreated so we can add another city if we choose. The rest of the code will behave in the same way.

当我们退出if块时,将重新创建该表单,以便我们选择添加另一个城市。 其余代码将以相同的方式运行。

结论 ( Conclusion )

And that's it! We now have a way to keep track of the weather for multiple cities in our app.

就是这样! 现在,我们可以在我们的应用程序中跟踪多个城市的天气。

In this article, we had to work with various parts of Django to get this working: views, models, forms, and templates. We also had to use the Python library requests to get the actual weather data. So even though the app is simple, you'll use many of the same concepts in apps with more complexity.

在本文中,我们必须使用Django的各个部分才能工作:视图,模型,表单和模板。 我们还必须使用Python库请求来获取实际的天气数据。 因此,即使应用程序很简单,您仍将在应用程序中使用许多相同的概念,但会更加复杂。

If you want to learn more about arguably the most important part of Django, models, you can join my free course called Django Database Essentials.

如果想更多地了解Django模型中最重要的部分,可以加入我的免费课程Django Database Essentials

翻译自: https://scotch.io/tutorials/building-a-weather-app-in-django

django中的app

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值