使用Django构建URL缩短应用的指南
学习Django或任何技能的最佳方法是通过创建功能性项目来应用您所掌握的知识。
Django是最常用的Python Web开发框架。其内置功能和大量的第三方软件包使其成为全球最受欢迎的之一。web frameworks
它快速、可靠,并具有许多内置功能。例如,它具有完整的认证系统,让您可以专注于应用的主要功能。此外,您还可以安装外部软件包来完成更复杂的任务,例如Django-allauth,它允许您使用社交账户注册用户。
但是让我们揭示一些事实。由于Django是一个庞大的框架,有时候很难入门。
所以今天您将从头开始构建一个完全功能的Django应用程序。
通过本教程结束时,您将:
- 编写一个URL缩短应用程序
- 了解Django MVT模式
- 学会创建一个项目的工作流程
先决条件
以下所有要求都是可选的,将帮助您跟随教程。但是如果您对其中任何要求都没有经验,不用担心。最重要的一步是第一步。
- 基本了解命令行操作(如ls、cd、rm、touch)
- 基本了解Python类和函数
- 在计算机上安装Python(可能是显而易见的,但我还是要包括)
- 如果您已经使用Django构建过某些东西,那就太棒了
所有工作代码将在此链接中提供。
现在您已经对前面的概念有了清晰的了解,让我们进入正题。
项目说明
在本教程中,您将构建一个URL缩短器。基本上,URL缩短器是一种将长URL转换为简短URL的服务。
例如,如果您想要分享一条推文,并希望包含指向您的网站的链接,但是您面临字符限制,您可以使用URL缩短器。
让我们用图形来看一下。
正如您所看到的,URL缩短器接收一个长URL并返回一个短URL。这正是您今天要构建的。
通过这个项目,您将练习使用MVT模式的使用,学习使用Django模型进行数据库设计的基础知识,并学习如何通过视图、URL和模板向用户显示信息。
Django项目的结构
基本上,Django网站是基于一个项目和多个独立的应用程序构建的。每个应用程序都具有特定的功能,并且能够独立工作。
让我们想象一个复杂的Web应用程序,比如StackOverflow。其功能基于两个主要方面。
- 用户管理:登录、注销、声望、权限
- 论坛:问题、答案、标签、过滤器
所以按照Django网站的结构,项目将被命名为StackOverflow,它有两个主要的应用程序,即用户应用程序和论坛应用程序。
这些应用程序中的每一个都具有独立的功能。这意味着它们都包含了它们正常工作所需的所有代码。
这包括模型(数据库结构)、视图(请求和响应)、特定的URL模式,当然还有模板和静态文件(图像、CSS、JavaScript)。这意味着任何Django应用程序都可以被重复使用,因为它们能够独立工作。
简而言之,项目是指一组配置和应用程序,旨在构建Web应用程序。另一方面,Django应用程序是项目的一部分,它是独立的(具有其正常工作所需的一切),其目的是执行特定的操作。
设置Django项目
在这个部分,您将要设置一个Django项目。为此,您将使用不同的工具,如Virtual environment to organize Python依赖项和最重要的Django脚本。Django-admin和manage.py
虚拟环境
我总是建议在使用Django构建应用程序时使用virtual environments。这是维护特定依赖关系集的最有效方式。但它的主要目的是将开发包与全局包隔离开来。
因此,让我们使用python内置的命令创建一个虚拟环境。
注意:此方法需要Python 3.6 or newer versions工作。
python -m venv .venv
此命令使用python -m或python –mod命令。从根本上讲,它运行一个模块或库,作为一个脚本。根据此命令的含义,venv是我们正在运行的库,.venv是我们想要创建的虚拟环境的名称。
所以用简单的语言来说,这个命令的意思是。
嘿Python,作为一个脚本运行内置库venv,并创建一个名为.venv的虚拟环境
现在,是时候激活我们刚刚创建的虚拟环境了,使用以下命令。
source .venv/bin/activate
为了确保您在新的venv中没有安装任何软件包,您可以运行。
pip freeze
如果您正确激活了虚拟环境,则不会得到任何输出。这是因为我们还没有安装任何东西。
让我们开始使用Django
为了创建我们的URL缩短应用程序,我们将首先安装Django包。Django是一个第三方包,因此我们需要使用Pip(Pip Installs Packages)进行安装。
$ pip install django
Collecting django
Downloading Django-3.2.1-py3-none-any.whl (7.9 MB)
|████████████████████████████████| 7.9 MB 344 kB/s
Collecting asgiref=3.3.2
Using cached asgiref-3.3.4-py3-none-any.whl (22 kB)
Collecting sqlparse>=0.2.2
Using cached sqlparse-0.4.1-py3-none-any.whl (42 kB)
Collecting pytz
Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Installing collected packages: asgiref, sqlparse, pytz, django
Successfully installed asgiref-3.3.4 django-3.2.1 pytz-2021.1 sqlparse-0.4.1
注意:记住$只是您的shell符号。
要检查安装是否正确,我们再次检查venv中安装的软件包。
$ pip freeze
asgiref==3.3.4
Django==3.2.1
pytz==2021.1
sqlparse==0.4.1
如果您获得的版本与我的不同,请不要担心。如果Django仍然是3.x版本,您可以继续进行。
开始一个Django项目
安装完Django后,现在是时候创建URL缩短网站的结构了。您还记得什么是Django项目吗?让我们通过运行以下命令来创建一个。
django-admin startproject config
解释一下这个命令,django-admin
是一个命令行实用程序,执行创建Django项目所需的所有任务。 “startproject”部分是Django-admin实用程序运行的命令,config是我们将要创建的项目的名称。
重要的是强调,config可以是任何您想要的名称。我之所以将config作为此项目的名称,只是因为方便。可以在不同项目之间切换,仍然保持相同的命名约定,所以不要害怕在任何时候使用其他项目名称。
正如您现在可能注意到的,您现在有一个config / 文件夹,在里面有许多文件。稍后我们将看到项目的文件结构。现在,让我们进入项目目录并运行本地服务器。
cd config/
您将使用的最重要的文件是manage.py 脚本。它具有与django-admin相同的功能,但使用它的主要优点是在运行项目时可以管理设置。
现在让我们看看是否一切正常。
python manage.py runserver
创建网址缩短应用程序
是时候创建项目的主要应用程序了。您将使用manage.py文件完成此任务。
python manage.py startapp urlshortener
这将创建一个名为urlshortener的Django应用程序。如果运行my_project/manage.py tree
命令,您将得到以下结果。
.
├── config
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── urlshortener
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
让我们澄清一下截至目前创建的不同文件。 “config”是我们项目的名称,只是为了遵守惯例而命名为这样。在config中,您可以找到settings.py
,它是您设置项目所有设置的文件。 urls.py
是项目中URL的整体配置。它定义了项目中所有应用程序的URL路径。
不要过于担心asgi.py
和wsgi.py
这些文件。这些是让您在部署中配置应用程序的文件。
manage.py
是一个python脚本,可让您运行所有可用的django-admin
命令。
查看urlshortener
,这是您刚刚创建的应用程序的名称,您可能会注意到有一个名为“migrations/”的奇怪文件夹和其他一些对于任何应用程序的逻辑至关重要的文件。
apps.py
是存储应用程序配置的位置。通常情况下,您不会对其进行修改,除非您正在进行非常高级的操作。
admin.py
是您在其中注册模型以使其在Django管理面板中可见的位置。
models.py
是最重要的文件。在这个模块中,您必须定义模型,它们(含糊地说)是数据的存储方式。您将在以后了解更多关于模型的内容。
migrations/
是存储Django迁移的文件夹。稍后我们将深入了解。
tests.py
是存储测试的文件。在本教程中不涉及测试。
views.py
是存储视图的文件。基本上,它定义了用户如何与您的应用程序的各个方面进行交互。
安装Django应用程序
在继续之前,打开settings.py
文件,并通过添加urlshortener应用程序来修改INSTALLED_APPS
变量。
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Custom apps
'urlshortener',
]
这是创建应用程序时的常规步骤。所以每次执行此操作时,请不要忘记在项目设置中安装它。
理解MVT模式
模型(Model),视图(View),模板(Template)模式是Django开发人员用于创建Web应用程序的软件设计模式。
它基于三个主要概念。模型(数据),视图(用户与数据的交互),模板(用户看到数据的方式)。
模型是Python类,定义了您希望存储的所有数据的字段和行为。通常,每个模型都指向数据库中的一个唯一表
视图在其最简单的表达中,是可调用函数,它接收用户的请求并生成响应。在这个过程中发生业务逻辑。我知道“业务逻辑”是一个相当模糊的概念,所以让我确切地解释一下。业务逻辑是数据创建、存储和删除的方式,仅此而已。
最后,模板是文本文档(通常是HTML),向用户显示。其目的是以尽可能清晰的方式呈现数据。Django包含了一种称为Django template language (DTL)的迷你语言,它允许您在文本文档中使用一些Python的强大功能。
创建Shortener模型
一旦您对MVT模式有了快速掌握,让我们从头开始创建Django URL缩短器。
首先,让我们在models.py
文件中定义缩短器模型。
'''
Url缩短器模型
'''
from django.db import models
# 在这里创建您的模型
class Shortener(models.Model):
'''
根据长链接创建一个短链接
created -> 创建短链接的日期和时间
times_followed -> 被点击的次数
long_url -> 原始链接
short_url -> 缩短的链接 https://domain/(short_url)
'''
created = models.DateTimeField(auto_now_add=True)
times_followed = models.PositiveIntegerField(default=0)
long_url = models.URLField()
short_url = models.CharField(max_length=15, unique=True, blank=True)
class Meta:
ordering = ["-created"]
def __str__(self):
return f'{self.long_url} to {self.short_url}'
我知道。这是一个非常庞大的类,有很多奇怪的东西,但不要绝望。我会逐步介绍每个重要部分。
模型解释
首先,我们导入models
模块。该模块包含创建Django模型所需的所有功能。
看看“Shortener”模型,首先要注意的是它扩展了models.Model
。实际上,任何Django应用程序中的任何模型都必须是models.Model类的子类。
然后,我们定义模型在数据库中将具有的所有字段。”created”字段是创建缩短链接的日期和时间,因此我们使用DateTimeField来创建这种功能。我们使用参数auto_now_add=True,因为我们希望该字段仅在创建实例时更改。
第二个字段times_followed
指的是缩短的URL已被使用的次数。它是一个PositiveIntegerField,我们指定默认值为零。这意味着每次创建实例时,Django都会将0填入times_followed
字段。
另一方面,long_url
指的是用户输入的URL。它是一个URLField,因为我们只希望用户输入http://yoursite.com
形式的字符。
最后一个字段是short_url
,它有一些有趣的细节。我们指定它只能是15个字符长,它必须是唯一的,这意味着该字段中不能有重复的元素。最后,我们指示它可以为空,这意味着在处理表单时,用户不需要编写自己的缩短代码。
内部的Meta类告诉我们类应该如何行为,我们设置短链接对象的排序(调用Shortener.objects.all()
)将由最近创建的对象辨别。
__str__
方法指定了模型如何打印。因此,如果我们有一个对象,长链接为“https://yaoweibin.cn/”,缩短部分为“123456”,并且我们将其打印出来。
https://yaoweibin.cn/ to 123456
现在是时候找到一种随机保存短链接的方法了。
创建缩短功能
我们将创建2个自定义函数。第一个函数将生成一个随机码,第二个函数将防止从Shortener模型中获取重复的随机码。为此,在“urlshortener”应用程序中创建一个名为utils.py的文件。
touch utils.py
在这个文件中,我们将使用random内置模块中的choose函数。这样可以更容易地选择随机字符来创建代码。
'''
Utilities for Shortener
'''
from django.conf import settings
from random import choice
from string import ascii_letters, digits
# 尝试从settings模块获取值
SIZE = getattr(settings, "MAXIMUM_URL_CHARS", 7)
AVAIABLE_CHARS = ascii_letters + digits
def create_random_code(chars=AVAIABLE_CHARS):
"""
创建预定大小的随机字符串
"""
return "".join(
[choice(chars) for _ in range(SIZE)]
)
如您所见,此函数返回一个指定长度的随机字符串,该长度可以通过设置文件或默认为7来指定。您使用getattr函数从settings模块获取变量,但如果未指定变量,则不会引发错误。
让我们进行一些计算。如果我们有7个位置,每个位置最多可以有62个可用字符,可能的链接如下:
基于这些快速计算,缩短部分的填充可以达到2500亿个不同的代码。所以我们可以忘记随机缩短URL的问题了。
尽管可能存在如此多的排列,但是得到重复的缩短部分的概率很小。这是一个问题,因为我们将shortened_url
字段设置为唯一的。这就是下面的函数非常有用。
def create_shortened_url(model_instance):
random_code = create_random_code()
# 获取模型类
model_class = model_instance.__class__
if model_class.objects.filter(short_url=random_code).exists():
# 再次运行函数
return create_shortened_url(model_instance)
return random_code
让我们看看这里发生了什么。该函数以“Shortener”模型实例作为参数。首先,该函数使用create_random_code
生成一个随机码。然后获取模型类并检查是否有任何其他对象具有相同的short_url
。如果有,则再次运行函数,否则返回随机码。
稍后,您将与shell进行交互,以便近距离查看此函数。
创建了实用函数后,让我们使用它在shortener模型中创建随机代码。
修改保存方法
在“Shortener”类的末尾,您将修改模型保存方法。每次将对象保存到数据库时,都会调用保存方法,因此我们将在这里看到如何使用它。
# 导入用于创建随机码的函数
from .utils import create_shortened_url
# 在Shortener模型末尾
def save(self, *args, **kwargs):
# 如果未指定短链接
if not self.short_url:
# 传递正在保存的模型实例
self.short_url = create_shortened_url(self)
super().save(*args, **kwargs)
save方法被重写,这意味着您正在为现有的父方法引入新的功能。基本上,它告诉Django每次保存“Shortener”对象并且未指定short_url
时,必须使用随机代码填充它。
运行迁移
现在是时候创建并运行Shortener模型的迁移了。要做到这一点,请在项目根文件夹中运行以下命令。
$ python manage.py makemigrations
Migrations for 'urlshortener':
urlshortener/migrations/0001_initial.py
- Create model Shortener
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, urlshortener
Running migrations:
......
# Apply the URL shortener migrations
Applying urlshortener.0001_initial... OK
目前,您不必担心迁移是什么。只需记住,当运行这两个命令时,Django会创建一个基于您定义的模型的迁移文件。
让我们在Django shell中创建一些对象。
$ python manage.py shell
>>> from urlshortener.models import Shortener
>>> s = Shortener(long_url="https://yaoweibin.cn")
>>> s.short_url
''
>>> s.save()
>>> s.short_url
'kdWFVIc'
>>> s.long_url
'https://yaoweibin.cn'
>>> print(s)
https://yaoweibin.cn to kdWFVIc
这就是所有缩短器对象的工作方式。
编写视图
如前所述,视图是一个简单的函数,接受一个请求并返回一个响应。因此,让我们看看如何创建一个hello world视图。
基本模板响应
在“urlshortener/views.py”文件中创建一个名为home_view的函数。
'''
短链接器视图
'''
from django.shortcuts import render, get_object_or_404 #稍后我们将使用它
from django.http import HttpResponse
# 在这里创建视图
def home_view(request):
return HttpResponse("Hello world")
它返回一个简单的消息“Hello world”。稍后您将看到它在浏览器中的样子。现在创建一个“urls.py”,其中将包含应用程序的所有URL模式。
touch urls.py
添加以下代码。
'''
短链接器应用的Urls urlshortener/urls.py
'''
from django.urls import path
# 导入home视图
from .views import home_view
appname = "shortener"
urlpatterns = [
# 主页视图
path("", home_view, name="home")
]
appname变量声明了urlshortener应用程序的命名空间。
简单解释一下,我们正在导入path function,它返回一个要包含在应用程序的urlpatterns中的元素。 name属性是该路径的命名空间,如果需要,可以在模板中调用它。
现在,让我们修改整个项目的URL。
# config/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
# 短链接器URL
path('', include('urlshortener.urls'))
]
现在让我们再次运行服务器。
python manage.py runserver
如果运行服务器,您将得到一个简单的“Hello world”消息。这是因为您将URL短链接器应用程序的urlpatterns包含在整个项目中。
这只是一个起点。现在是时候创建一个表单,让用户自己创建缩短的URL。
创建表单
在Django中,form是一个简单的类,允许从用户那里获得输入。
您将创建一个forms.py文件。将所有表单存储在该文件中是一种约定。
cd urlshortener/
touch forms.py
在这个文件中,您将创建一个名为“ShortenerForm”的类,它继承自“ModelForm”。
'''
urlshortener/forms.py中的Shortener Forms
'''
from django import forms
from .models import Shortener
class ShortenerForm(forms.ModelForm):
long_url = forms.URLField(widget=forms.URLInput(
attrs={"class": "form-control form-control-lg", "placeholder": "Your URL to shorten"}))
class Meta:
model = Shortener
fields = ('long_url',)
这是一个模型表单,因为其目的是根据用户输入创建模型对象。我们还使用widget参数,它允许我们指定“class”(CSS中的class,而不是python)属性。这是因为我们将在后面使用bootstrap来样式化应用程序。
完成视图
在构建表单之后,是时候创建应用程序的最终业务逻辑了。
导航到shortener应用程序中的views.py
文件,并修改home_view
视图。您可以此时查看Github repo,以了解项目结构的外观。
URL缩短器应用程序有两个视图:
- 主页视图:显示缩短器表单和如果已提交表单,则显示新的URL。
- 重定向视图:重定向到长URL并将次数加1。
让我们从最复杂的主页视图开始。您需要导入Shortener模型和表单。由于我希望您理解视图的所有数据流,所以仍然使用函数。此外,您将使用一个模板的路径(尚未创建)。
主页视图
'''
Shortener views
'''
from django.shortcuts import render # 我们稍后将使用它
from django.http import HttpResponse, Http404, HttpResponseRedirect
# 模型
from .models import Shortener
# 自定义表单
from .forms import ShortenerForm
# 在此处创建您的视图。
def home_view(request):
template = 'urlshortener/home.html'
context = {}
# 空表单
context['form'] = ShortenerForm()
if request.method == 'GET':
return render(request, template, context)
elif request.method == 'POST':
used_form = ShortenerForm(request.POST)
if used_form.is_valid():
shortened_object = used_form.save()
new_url = request.build_absolute_uri('/') + shortened_object.short_url
long_url = shortened_object.long_url
context['new_url'] = new_url
context['long_url'] = long_url
return render(request, template, context)
context['errors'] = used_form.errors
return render(request, template, context)
该视图基于两个条件:
- 当HTTP方法等于GET时:我们只将用于创建Shortener对象的Shortener表单作为上下文传递。
- 当HTTP方法等于POST时:我们仍然将表单传递给上下文,因为我们希望用户能够输入另一个URL。但是我们将Post请求传递给另一个名为used_form的表单。
一种以安全方式处理错误请求(用户未输入有效的URL)的方法是获取表单错误,将其作为上下文传递并按正常方式呈现模板。稍后您将看到如何在模板中实现错误显示。
重定向视图
这个 redirect_url_view
是一个更简单的视图。它是一个详细视图,这意味着视图只适用于一个对象。
这个函数接受用户的请求和 URL 的 缩短部分 作为参数。由于我们在该视图中不使用表单,所以不需要断言请求的类型。
def redirect_url_view(request, shortened_part):
try:
shortener = Shortener.objects.get(short_url=shortened_part)
shortener.times_followed += 1
shortener.save()
return HttpResponseRedirect(shortener.long_url)
except:
raise Http404('对不起,此链接已损坏 :(')
我们用 try/except 语句保护这个视图,以防缩短部分在数据库中找不到。如果找到对象,它会将 times_followed
字段加 1,并使用 HttpResponseRedirect
函数重定向到对应于随机代码的站点 URL。
更新 URL
一旦你创建了应用程序的两个视图,就可以通过包含路径到 redirect_url_view
来创建最终的 URL 模式。
和往常一样,你首先导入视图,然后创建一个路径函数并传入参数:
- URL 路由
- 指向路径的视图
- 路径的名称
'''
Urls for shortener app urlshortener/urls.py
'''
from django.urls import path
# 导入 home 视图
from .views import home_view, redirect_url_view
appname = "shortener"
urlpatterns = [
# Home 视图
path('', home_view, name='home'),
path('', redirect_url_view, name='redirect'),
]
有了这个 URL 配置,应用程序的路由如下:
localhost:8000/
: Home 视图localhost:8000/URL-code
: 重定向到长 URL
创建模板
你离构建这个应用程序只差一步了。唯一隔离你和完成应用的是用户界面。为此,我们使用 Django 模板。
模板用于为应用程序用户渲染一个清晰的界面。这些文件在应用程序内以 “templates/appname” 的双重文件夹结构创建。
# urlshortener 目录
mkdir -p templates/urlshortener/
注意:双重文件夹结构和 Django 模板语言超出了本教程的范围,但你可以在 official documentation中了解它们。
基本模板
Django 允许模板继承。这意味着我们可以有一个基本模板,并通过继承它来遵循 DRY(不要重复自己)原则。
cd templates/urlshortener
touch base.html
base.html 文件是一个约定,意味着应用程序的每个其他模板都必须是对它的扩展。
{% block body %}
{% endblock body %}
我们将使用bootstrap CDN,以便快速创建漂亮的界面而无需CSS或。
如果您想深入了解DTL标签,可以通过进行学习。
主页模板
主页模板继承自base.html文件。这意味着该模板包含父文件中的所有HTML。
{% extends ‘urlshortener/base.html' %}
{% block body %}
URL缩短应用
{% if errors %}
{{errors}}
{% endif %}
{% if new_url %}
您的缩短链接
您可以复制下面的链接并与您的朋友分享
{{new_url}}
原始链接:{{long_url}}
{% endif %}
{% endblock body %}
我将快速解释一下该模板的数据流程:
显示缩短器表单。在表单内,设置了(出于安全原因),并且只显示表单的长URL字段。请记住,该字段具有CSS类“form-control form-control-lg”,因为我们在表单中设置了这个类。
如果发现任何错误,则显示它们。
如果POST操作成功,则显示新的URL。
最终应用程序
恭喜!🎉 您已经使用Django构建了一个完整的功能性URL缩短器应用程序。
以下是应用程序的一些屏幕截图。
只获取:
缩短URL出错:
成功缩短URL:
URL重定向:
您认为向某人展示此URL缩短器应用程序的演示如何?请查看。
挑战🔥
如果您对Django技能感到满意,为什么不尝试一个挑战呢?
克隆此应用程序的代码,并创建一个身份验证系统,只有注册用户才能缩短其URL。
完成后,发送拉取请求并在上提及我以展示您的成就。
总结
您已经到达本教程的末尾。无论您相信与否,您刚刚回顾了创建Django项目的所有主要方面。希望您觉得非常有用。
在本教程中,您:
学习了创建Django应用的工作流程。
构建了一个简历项目。
了解了Django项目和Django应用的区别和结构。
了解了MVT模式。
创建了函数基视图。
使用Django ORM(对象关系映射器)创建了简单模型。
就是这样了,关于Django还有很多内容要涵盖,敬请关注更多精彩的教程。