在 PyCharm 中创建 Django 应用
Django 的核心思想是让开发者快速构建应用程序。 掌握这个框架后,从概念到可以投入生产的 Web 应用程序的路径将大幅缩短。 但是,如果您还想更快,可以学习在 PyCharm 中创建 Django 应用。
本教程将通过一系列步骤指导您创建一个简单的 Django 应用程序,显示所在位置的当前气温。 为了增加互动性,这款应用还可供浏览其他随机位置的天气状况。
在本教程中,您将学习如何:
- 在 PyCharm 中创建 Django 项目。
- 编写模型、视图和模板。
- 进行 API 调用并处理响应。
- 连接到数据库并使用数据填充。
克隆仓库即可获取完整的应用程序代码。 要了解有关克隆的信息,请参阅 PyCharm 文档。
前提
本教程适合已经有数年 Python 经验的开发者。 因此,我们假设您的电脑上已经安装了 Python。 如果不是这样,也别担心! 开始在 PyCharm 中创建第一个项目时,您可以下载并安装需要的 Python 版本。
对 Django 的支持是一项专业功能,因此您需要 PyCharm Professional。 新用户有 30 天的免费试用期,如果您是学生或教师,可以申请免费教育许可证。 本教程基于已启用新 UI 的 PyCharm 2023.1。
有关不同操作系统的更多信息和安装说明,请参阅 PyCharm 文档。
开始构建应用
我们先迈出第一步。 步骤不多,最后,您将得到一个基础应用。
在 PyCharm 中创建 Django 项目
要创建项目,首先启动 PyCharm 并点击 New Project(新建项目)。 如果 PyCharm 已经在运行,可以从主菜单中选择 File | New Project(文件 | 新建项目)。
在打开的 New Project(新建项目)窗口中,指定以下信息:
- 选择 Django 作为项目类型。
- 输入项目所在目录的名称。 这也将用作项目名称。
- 为新 Django 项目创建虚拟环境,PyCharm 将在其中安装依赖项。 在本教程中,我们将选择 virtualenv 选项。
- PyCharm 可以立即在项目中创建 Django 应用程序。 务必在这里为应用程序命名。
准备好后,点击 Create(创建)。 PyCharm 创建文件结构,并安装 Django 和其他需要的依赖项。
点击窗口顶部的 Run(运行)图标启动 Django 服务器:
这将打开 Run(运行)工具窗口。 点击链接打开浏览器窗口:
在 PyCharm 中启动 Django 服务器只需要几分钟的时间。 这是一个好的开始,但最好的还在前面。
编写首个视图
现在,开始创建应用程序逻辑。 在 Django 中,在 views.py 中编写类或函数。
您可以随时点击 PyCharm 窗口左上角的文件夹图标,也可以按 ⌘1 / Alt+1 来探索项目的结构:
本教程包含可以节省大量时间的快捷键,例如按两次 ⇧ (Shift) 键可以打开 Search Everywhere(随处搜索)窗口。 这个快捷键可以找到任何内容,包括项目文件、设置和操作。
我们用它来快速打开 views.py。
输入 views,将光标移动到 meteo 处的 views.py,然后按 Enter:
带有 views.py 的编辑器标签页随即打开。 我们先编写一个 temp_here
函数,它将返回我们位置的当前温度。
在编辑器中粘贴以下代码:
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()
这里发生了什么? 首先,导入 API 调用所需的 requests
库。 如果 import 语句中有红色波浪线,则表示软件包在所选 Python 解释器中不可用。
将光标悬停在它上面,选择 Install package requests(安装软件包请求)。
为了获取当前温度,temp_here
会调用 Weather Forecast API。 这是一个不需要 API 密钥的免费 API。 我们只需要知道端点 (https://api.open-meteo.com/v1/forecast) 和坐标。 对于后者,我们将使用 Geocoder – 这是一个非常简单的 Python 库,可供检索不同位置的坐标。
将文本光标放在以红色波浪线高亮显示的 geocoder
上,然后按 ⌥Enter / Alt+Enter 查看可用的快速修复。 选择 Install and import package ‘geocoder’(安装并导入软件包 ‘geocoder’):
PyCharm 会安装软件包并将 import 语句添加到文件的开头。
那么,如何发出测试请求来确保一切按预期工作? 最简单的方式是在 Python 控制台中调用函数。
我们来使用另一个节省时间的方式 – Find action(查找操作)。 不用在菜单中滑动鼠标,也不用背下几十个快捷键,只需按 ⇧⌘A / Ctrl+Shift+A,然后搜索 Run File in Python Console(在 Python 控制台中运行文件)。
您不需要打出整个单词。 使用 rufipy 这样的词也会得到想要的结果:
运行命令时,PyCharm 会将 import 和函数定义加载到控制台中。 现在,调用 temp_here
。 按 Tab 键可以补全代码:
检查来自控制台输出的 API 响应。 这个字符串很长,但下面有说明性表示。
如果要探索响应,可以遵循以下步骤:
- 点击 3 次控制台输出,然后按 ⌘C / Ctrl+C 将其复制到剪贴板。
- 按 ⇧⌘N / Ctrl+Alt+Shift+Insert 创建临时文件,然后选择 JSON 文件类型(输入 js… 即可)。
- 粘贴响应并应用 Reformat Code(重新格式化代码)操作。 可以使用 Find action(查找操作)或按 ⌥⌘L / Ctrl+Alt+L。
所需信息位于 temperature_2m
键下的 hourly
元素中。 此键指向一个值列表。
为了获取当前温度,我们必须将当前小时作为索引。 例如,如果现在是 14:30,我们将使用列表的第 14 项。
看一下 temp_here()['hourly']['temperature_2m'][14]
是否提供了需要的信息。
根据当前时间替换 14,并在控制台中输入代码:
14.9 °C 是我们所在位置的当前温度。 您那里呢?
修改函数,让它从 API 响应中提取当前温度:
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
记得导入 datetime
:
点击 Python 控制台工具栏左上角的 Rerun(重新运行),重新加载更新的函数定义,然后再次调用 temp_here
:
如果结果与更改 temp_here
函数代码之前的结果不同,那可能是因为 settings.py 中的 TIME_ZONE
值错误。
有关详情,请参阅 Django 文档。
要快速访问此设置,首先按两次 ⇧ (Shift),按几次 Tab 切换到 Symbols(符号),然后输入 time…。
接下来,将 temp_here
变成视图函数。 要被 Django 识别为视图,函数必须接受 HttpRequest 对象作为其第一个形参,通常命名为 request
。 它还应该返回 HttpResponse 对象。
以下是 views.py 的样子:
from datetime import datetime import geocoder as 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}")
如您所见,我们没有做太多更改:temp_here
现在接受 request
作为实参并返回带有字符串的 HttpResponse
。
如果您偏好华氏度而不是摄氏度,这很容易实现,只需将 temperature_unit
形参添加到 API 请求:
api_request = f"{endpoint}?latitude={location[0]}&longitude={location[1]}&hourly=temperature_2m&temperature_unit=fahrenheit"
如果您更喜欢使用摄氏度,则跳过此修改。
配置 URL
更新 urls.py,配置从浏览器访问应用的方式。 按两次 Shift,输入 urls,如上所述查找和打开。
将以下行添加到 urlpatterns
。 使用 Reformat Code(重新格式化代码)操作 ⌥⌘L / Ctrl+Alt+L 可以在粘贴后轻松还原缩进:
path("", include('meteo.urls')),
不要忘记从 django.urls.include
导入 include
。
'meteo.urls'
现在被标记为带有黄色波浪线的未解析引用,因为文件尚不存在。 这将在后续步骤中得到修正。
Django 项目通常包含多个应用。 即使目前并非如此,也要考虑项目的未来发展。 因此,我们在对应文件夹中为每个应用程序创建 urls.py ,然后将它们全部添加到项目的 urls.py 中。
接下来,在 meteo 应用程序的文件夹中创建 urls.py。
在 Project(项目)工具窗口中右键点击 meteo 目录。
选择 New > Python File(新建 > Python 文件),输入 urls。
新创建的文件将打开。 使用以下代码填充:
from django.urls import path from . import views urlpatterns = [ path('meteo/', views.temp_here, name='temp_here'), ]
现在,当我们在浏览器中转到 <server_address>/meteo 时,views.py 中的 temp_here
函数将被调用,浏览器将渲染函数返回的任何内容。
它上线了!
点击右上角的 Rerun(重新运行)按钮重新运行 Django 服务器并确认操作:
在浏览器中打开 http://127.0.0.1:8000/meteo/。 您看到的内容应该类似于:
如果您不想在每次重新启动 Django 服务器时打开浏览器输入地址,或手动刷新页面,可以将 PyCharm 配置为代您完成这些操作。
打开 Run(运行)微件中的下拉菜单,选择 Edit configurations(编辑配置):
在左窗格中选择项目的配置,启用 Run browser(运行浏览器)复选框,然后将 meteo 添加到 url:
点击 OK(确定)应用更改。
基本上,应用已经可以运行了。 但它在浏览器中不太好看,而且仍然没有“随机位置天气”功能。 在接下来的步骤中,我们将引入模板并导入数据来解决这些问题。
改进体验
添加模板
我们回到 views.py,再次修改 temp_here
函数。 如果您还在 meteo/urls.py 中,可以立即导航到那里。 按住 ⌘ / Ctrl,将鼠标悬停在 temp_here
上,当它变成超链接时点击:
在 return 语句之前开始一个新行并输入“template = loader”。
按 ⌥Enter/ Alt+Enter 并使用快速修复从 django.template.loader
导入 loader
:
然后,使用 get_template()
加载 index.html 作为模板:
template = loader.get_template('index.html')
现在,将 return 语句替换为以下两行:
context = {'temp': temp} return HttpResponse(template.render(context, request))
Index.html 以黄色波浪线高亮显示,因为它尚不存在。 将光标悬停在它上面并选择 Create template index.html(创建模板 index.html)。
点击 OK(确定)。 PyCharm 将创建 index.html 并打开它进行编辑。
文件现在为空。 使用 Live Template(实时模板)填充模板 html 代码。 输入 html:5,按 Tab:
html 页面的可见内容位于 <body></body>
标记之间。
在这里插入以下代码:
<h1>Temperature at your location:</h1> <h2>{{ temp }} ℃</h2>
temp
是从视图传递给模板的变量。 变量的名称和值应保存到字典中,并在渲染模板时传递。 为此,我们将 {‘temp’ : temp}
赋给以上 views.py 中的上下文变量。
摄氏度符号的 Unicode 表示是 ℃
。 华氏度使用 ℉
。
接下来,重新运行 Django 服务器查看更改,并确保应用按预期工作。 如果您已按上述说明编辑了运行配置,浏览器窗口应自动打开:
创建数据库和模型
为了从 API 获取随机位置的温度数据,我们需要提供这些位置的坐标。
为此,使用 Juanma Hernández 在 CC BY 4.0 许可下提供的 World cities 数据库。 下载数据库并从归档提取 worldcities.csv。 如果您在 Kaggle 还没有帐户,则必须注册。
我们还需要将 Django 自动创建的 db.sqlite3 数据库添加到我们的 PyCharm 项目。
为此:
- 点击右侧的数据库图标打开 Database(数据库)工具窗口。 您也可以按 ⌘E / Ctrl+E 访问所有工具窗口:
- 点击工具窗口左上角的 +,选择 Data Source > SQLite(数据源 > SQLite)。 输入 sq… 可以更快地找到所需选项:
- 点击 File(文件)字段旁边的 …,在项目文件夹中查找 db.sqlite3 文件。
- 您可能需要安装、更新或切换数据库驱动程序。 如果窗口底部出现警告,则点击链接执行所需操作:
- 点击 OK(确定)。
为了将数据导入数据库,应在 Database(数据库)工具窗口中将 worldcities.csv 拖放到 db.sqlite3。 在打开的对话框中,移除不必要的列,只保留 city、lat、lng、country 和 id:
现在,db.sqlite3 数据库包含 worldcities 表:
双击即可在编辑器中查看其内容。
Django 使用模型与数据库交互。 创建一个模型来实现从 worldcities 表读取数据。
- 按 ⌥R / Ctrl+Alt+R 启动 manage.py 任务控制台。
- 输入 inspectdb worldcities 并按 Enter。
- 将
Worldcities
类从控制台输出复制到 meteomodels.py。 - 将 id 字段的
null=True
替换为primary_key=True
。
以下是它的样子:
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'
添加功能
目前为止,我们在 views.py 中只有一个函数 (temp_here
) 可以返回有关您所在位置当前温度的信息。 我们再添加一个函数来显示随机位置的温度。 它也需要从 API 获取当前温度数据,因此根据 Python 最佳做法,我们应该将该功能移动到单独的函数。
在 PyCharm 中,这可以通过 Extract method(提取方法)重构轻松完成。
选择应移至单独函数的行,然后按 ⌥⌘M / Ctrl+Alt+M。 或者,使用 Find Action(查找操作):
在 Method name(方法名称)字段中指定 get_temp
,然后点击 OK(确定)。 我们现在有了接受 location
作为唯一形参的 get_temp
函数。
temp_here
函数调用它来接收当前位置的温度。
我们来创建 temp_somewhere
函数。 它应该将随机城市的坐标传递给 get_temp
。
首先,在 Python 控制台中进行一些原型设计。 打开并粘贴以下代码(如果出现 ImportError
,则关闭并重新打开控制台):
from meteo.models import Worldcities random_item = Worldcities.objects.all().order_by('?').first()
我们需要从 worldcities 表获取数据。 这是通过模型完成的,因此我们从 models.py 导入 Worldcities
模型。
然后,使用 order_by(‘?’)
随机化所有对象并使用 first()
获得第一个对象。 在 Python console(Python 控制台)工具窗口的右侧,有一个 Variables(变量)标签页。 展开 random_item 节点,查看 random_item
的内容:
temp_somewhere
函数的完整代码如下所示:
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))
除了温度,context
现在还包含城市名称。 我们来编辑模板,使其也呈现此信息。
您可能已经注意到装订区域中的 <> 图标。 点击以快速切换到 index.html:
将 <h1></h1>
标记之间的文本替换为 {{ city }}
:
点击装订区域图标可快速访问 temp_here
函数:
我们需要修改它,使它也传递 city
变量:
在浏览器中打开 https://127.0.0.1/meteo 页面时将调用 temp_here
函数,我们已在 meteo/urls.py 中完成配置。
我们回到那里,指定在访问 https://127.0.0.1/meteo/discover 时应调用 temp_somewhere
:
urlpatterns = [ path('meteo/', views.temp_here, name='temp_here'), path('meteo/discover', views.temp_somewhere, name='temp_somewhere'), ]
返回 index.html,添加指向 /discover 页面和首页的链接。 后者将始终显示当前位置的温度。 实时模板和代码补全可以节省大量时间:
要对 html 文件中的段落和链接使用实时模板,只需分别输入 p 或 a ,然后按 Tab。
要查看可用实时模板的完整列表,首先打开设置 (⌘ / Ctrl+Alt+S),转到 Editor > Live Templates(编辑器 > 实时模板),然后展开右窗格中的 Zen HTML 节点:
您可以重新运行服务器并试用应用程序:
还没结束
应用现在可以运行,但还有改进的空间。 最明显的是视觉外观,但也还可以添加额外功能。
使用 CSS
CSS 是使 Django 应用程序看起来更好的最快也最简单的方式。 例如,使用 Simple.CSS。
将以下行放在 index.html 中 <head></head>
标记之间的任意位置:
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
新外观:
将链接替换为按钮也将改善外观:
为此,将 index.html 中 <p></p>
标记之间的链接替换为以下 html 代码:
<div style="display: flex;"> <form action="./discover"> <input type="submit" value="Check other places"/> </form> <form action="."> <input style="background: #dc3545" type="submit" value="Home"/> </form> </div>
无需从 PyCharm 切换到浏览器即可看到编辑 index.html 的结果。 将鼠标悬停在编辑器窗口的右上角,选择 Built-in Preview(内置预览):
使用 Bootstrap
Bootstrap 是一个强大且免费的前端工具包。 要将它快速应用到 Django 应用,按如下所示编辑 index.html(有关详情,请参阅 Bootstrap 快速入门指南):
- 将
link
标记添加到 html 头部(替换前面步骤中的 simple.css):
<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. 在 <body></body>
标记内添加以下代码:
<div class="container text-center"> <h1>{{ city }}</h1> <h2>{{ temp }} ℃</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>
查看结果:
Bootstrap 提供了多种自定义应用外观的方式。 您可以在文档中找到所有必要信息。
亲自尝试
我们已将 worldcities 数据库的 country
字段添加到 Worldcities
模型中,但并未在应用的任何地方使用该数据。 现在,您还可以测试自己的技能,让应用除了城市名称之外还显示国家/地区。 结果应该类似于:
总结
在本教程中,我们学习了如何:
- 在 PyCharm 中创建 Django 项目。
- 编写视图和创建模板。
- 进行 API 调用并处理响应。
- 连接数据库和导入数据。
- 应用 CSS 和 Bootstrap 改善应用的视觉外观。
本博文英文原作者: