I decided it was time to upgrade my personal website in order to allow visitors to buy and access my courses through a new portal.
我认为是时候升级我的个人网站了,以允许访问者通过新的门户购买和访问我的课程 。
Specifically, I wanted a place for visitors to sign up for an account, view my available courses, and purchase those courses. Once a user had purchased a course they would be able to access all of the content in the course forever. This may sound simple in theory. However, without using an ecommerce site such as Shopify, membership sites are surprisingly complex.
具体来说,我想为访问者提供一个注册帐户,查看我的可用课程并购买这些课程的地方。 用户购买课程后,他们将能够永久访问课程中的所有内容。 从理论上讲,这听起来很简单。 但是,如果不使用Shopify这样的电子商务网站,则会员网站非常复杂。
In this article I will walk you through the decisions I made and the technology stack I used to build this new site, including:
在本文中,我将带您逐步了解我所做的决策以及用于构建该新站点的技术堆栈,包括:
- How to start? 如何开始?
- Starting a Django Project 启动Django项目
- How to set up Django models 如何建立Django模型
Integrating Stripe Payments
整合条纹支付
- Deploying my new site on an AWS EC2 instance 在AWS EC2实例上部署新站点
- How to clone CSS from an existing page 如何从现有页面克隆CSS
如何开始? (How To Start?)
When adding a new section to your website with a completely new feature set, it’s logical to organize this site as a subdomain of your original site.A subdomain is exactly what it sounds like. It's a domain that is part of another (main) domain. Subdomains appear as a new section of your domain url before the main domain url.
当将具有全新功能集的新部分添加到您的网站时,将此网站组织为原始网站的子域是合乎逻辑的。 该域是另一个(主)域的一部分。 子域名在您之前显示为您的域名网址的新部分 主域网址。
More specifically:
进一步来说:
My main domain is: https://nickmccullum.com
我的主要域名是: https : //nickmccullum.com
My new courses subdomain is: https://courses.nickmccullum.com
我的新课程子域是: https : //courses.nickmccullum.com
The main advantage of a subdomain is that they are free! Not to mention, a subdomain tagged on to an already-well-ranked site gets indexed quickly and benefits from its parent’s success.
子域的主要优势在于它们是免费的! 更不用说,标记到已经排名不错的网站上的子域会快速被索引,并受益于其父级的成功。
I knew that I would need a server to host my new site. I would also need to attach that server with an elastic IP address.
我知道我需要一台服务器来托管我的新站点。 我还需要为该服务器附加一个弹性IP地址。
An elastic IP address is a static IP that will never change. This means it can be accessed by the public 24/7.
弹性IP地址是不会更改的静态IP。 这意味着公共24/7可以访问它。
The fastest way to get a server up and running nowadays is to host it in the cloud. There are many options for cloud computing, including as Amazon's AWS, DigitalOcean's Droplets, or Azure's Containers. In terms of pricing, the options available are all fairly equal across the board - so that didn’t factor into my decision too much.
如今,使服务器启动并运行的最快方法是将其托管在云中。 云计算有很多选择,包括Amazon的AWS , DigitalOcean的Droplet或Azure的Containers 。 在定价方面,所有可用选项在各个方面都相当平等-因此,这并没有过多地影响我的决定。
I’ve had previous experience with AWS (Amazon Web Services) - a cloud based service for hosting infrastructure. Naturally I chose to host my server here. To be more specific, I am hosting the site on an EC2 instance. We will talk more about that later.
我以前有过AWS(Amazon Web Services)的经验-AWS是用于托管基础架构的基于云的服务。 自然,我选择在这里托管服务器。 更具体地说,我将站点托管在EC2实例上。 稍后我们将详细讨论。
Okay, so now I knew where I wanted to host my new website, what’s next? It was time to think about the tech stack for the site. When thinking about what technology to use for building your website, it's important to consider these major topics:
好的,现在我知道要在哪里托管新网站了,下一步是什么? 现在是时候考虑该站点的技术堆栈了。 在考虑使用什么技术来构建网站时,重要的是要考虑以下主要主题:
- What you are proficient in 你精通什么
- Choosing frontend and backend technologies that mesh well together 选择可以很好地融合在一起的前端和后端技术
- The performance of the site 网站的表现
You should answer these questions and try to choose a technology stack that suits your needs and abilities. For me, I am most proficient in Python, so Django 3.0 was a natural choice!
您应该回答这些问题,并尝试选择适合您的需求和能力的技术堆栈。 对我来说,我最精通Python,因此Django 3.0是自然的选择!
I had worked on a Django app before (Passiv) so I was broadly familiar with the infrastructure. However, I had never built a Django project from scratch.
我之前( Passiv )曾经从事过Django应用程序的工作,因此我对基础架构非常熟悉。 但是,我从未从头开始构建Django项目。
Because of this, I had some reading to do. As I learned more about this popular framework I kept comparing it to PHP, the popular web programming tool. I have worked on multiple Wordpress sites in the past, and Wordpress is built on PHP, so this was a natural comparison (at least for me).
因此,我需要阅读一些内容。 随着我对这个流行框架的了解越来越多,我一直将它与流行的Web编程工具PHP进行比较。 我过去曾在多个Wordpress网站上工作,而Wordpress是基于PHP构建的,因此这是自然的比较(至少对我而言)。
According to their documentation and various posts on Stackoverflow, here are the main differences between the Django framework and the major PHP frameworks:
根据他们的文档和有关Stackoverflow的各种文章,这是Django框架与主要PHP框架之间的主要区别:
- Django is more focused on security by default and provides built-in security practices to help programmers save time during development. 默认情况下,Django更加关注安全性,并提供内置的安全性实践来帮助程序员节省开发时间。
- Django is focused on speed. It's known as a framework which helps developers get their sits off the ground as quickly as possible. Django专注于速度。 它被称为框架,可帮助开发人员尽快摆脱困境。
- Django has marginally lower performance compared to most PHP-based frameworks. 与大多数基于PHP的框架相比,Django的性能略低。
I’d like to touch on that last point. Python is an interpreted language and is commonly associated with a lower performance than other programming languages. When a new programmer hears something like this they may think that Python is much worse than other language choices because of the importance of performance in computing.
我想谈谈最后一点。 Python是一种解释型语言,通常与其他编程语言相比具有较低的性能。 当新程序员听到这样的消息时,他们可能会认为Python比其他语言选择差很多,因为在计算中性能的重要性。
Though Python does have lower performance standards compared to other languages this is an extremely vague statement. In fact, the difference between Django and Laravel (a popular PHP based framework) is so small it's considered negligible.
尽管与其他语言相比,Python确实具有较低的性能标准,但这是一个非常含糊的陈述。 实际上,Django和Laravel(一种流行的基于PHP的框架)之间的差异是如此之小,以至于可以忽略不计。
For this performance difference to matter to you, you would need to be writing a highly performance-dependent application with millions of users. I was encouraged to learn that many of the world's largest web applications are built on Django. Said differently, if Django is good enough for Instagram, then it was certainly performant enough for my site.
为了使这种性能差异对您很重要,您需要编写具有数百万个用户的高度依赖于性能的应用程序。 令我感到鼓舞的是,世界上许多最大的Web应用程序都是基于Django构建的。 换句话说,如果Django对于Instagram来说已经足够好了,那么对于我的网站来说,它的性能肯定足够。
In the end I decided to build my courses website using Django mainly because I have experience with Python. Learning a new web framework was a nice bonus.
最后,我决定使用Django建立课程网站,主要是因为我有使用Python的经验。 学习一个新的Web框架是一个不错的收获。
Next, I knew I was going to need a database for this site. Having experience with MySQL and PostgreSQL, I was originally going to resort to using it again here. However, Django ships default with an SQLite3 database service that requires minimal setup. I have never used SQLite so I did some more research.
接下来,我知道我将需要该网站的数据库。 拥有MySQL和PostgreSQL经验,我本来打算再次在这里使用它。 但是,Django附带了默认情况下需要最少设置SQLite3数据库服务。 我从未使用过SQLite,所以我做了一些进一步的研究。
Based on the performance and data storage needs, the default SQLite3 database shipped with Django would be more than powerful enough for my site. I was shocked to find that a lighter version of a database service could be so powerful!
根据性能和数据存储需求,Django附带的默认SQLite3数据库对于我的网站而言已经足够强大。 我震惊地发现,轻量级的数据库服务如此强大!
For anyone unfamiliar with this technology (like I was), SQLite3 is a relational database with great performance for sites with low to medium levels of traffic (~100K hits per day). SQLite3 can be run on the same server as the website without impacting performance. This means that I did not need to spin up a separate Amazon RDS instance, which saves some money in the deployment stage.
对于不熟悉这项技术的人(就像我以前一样),SQLite3是一个关系数据库,对于低到中等流量水平(每天点击约10万次)的站点而言,它具有出色的性能。 SQLite3可以与网站在同一服务器上运行,而不会影响性能。 这意味着我不需要启动单独的Amazon RDS实例,从而在部署阶段节省了一些钱。
启动Django项目 (Starting a Django Project)
Django is a high-level python web framework with the main goal of allowing rapid development and providing security by default. It takes care of many hassles of web development, reducing repetitive coding practices.
Django是高级python Web框架,其主要目标是允许快速开发并默认提供安全性。 它解决了Web开发的许多麻烦,减少了重复的编码实践。
One of the best parts of using Django is that it is absolutely free.
使用Django最好的部分之一是它完全免费。
Django is designed to help developers get their websites off the ground quickly (which is one of the main reasons I chose to use it for this project). One of my favourite features of this framework (as with most others) is their frontend templating system. Django Templates allow you to write dynamic code which then generates the desired HTML and CSS. This gives you the ability to use structures such as loops and if statements in order to create dynamic HTML code (meaning it renders differently for each user) that can then be served as a static file. For example:
Django旨在帮助开发人员快速启动其网站(这是我选择在此项目中使用它的主要原因之一)。 我的最喜欢的功能(与大多数其他功能一样)是它们的前端模板系统。 Django模板允许您编写动态代码,然后生成所需HTML和CSS。 这使您能够使用循环和if语句之类的结构来创建动态HTML代码(这意味着每个用户的呈现方式有所不同),然后可以将其用作静态文件。 例如:
# course_titles_template.html
{% for course in courses_list %}
<h1>{{ course.course_title }} </h1>
{% endfor %}
Would create a heading for every course variable found in the courses_list
object. This could would render an HTML file with an <h1>
tag that contains the title of each course, like this:
将为在courses_list
对象中找到的每个课程变量创建一个标题。 这样可以呈现一个带有<h1>
标签HTML文件,该标签包含每个课程的标题,如下所示:
<h1> Python Fundamentals </h1>
<h1> Advanced Python for Finance and Data Science</h1>
<h1> How to Run Python Scripts </h1>
<h1> How to Make A Python Class </h1>
The templating system saves you from a lot of manual labor. Allowing the HTML to render dynamically saves you the headaches of updating your code every time you add a new object. This templating system also allows the web app to update over time as I add more content. So in this case if I were to add a new course to my database, this template would not need to be changed. It would simply render my new course’s title in a new heading tag.Django also makes it extremely easy to get started in a project. Once you have Django installed, you are able to use the django-admin
in order to start a project and even set up your apps.
模板系统使您免除了大量的体力劳动。 允许HTML动态呈现可以避免您每次添加新对象时更新代码的麻烦。 当我添加更多内容时,该模板系统还允许Web应用程序随时间更新。 因此,在这种情况下,如果我要将新课程添加到数据库中,则无需更改此模板。 它只是将新课程的标题显示在新的标题标签中.Django也使在项目中入门变得非常容易。 一旦安装了Django,就可以使用django-admin
启动项目,甚至设置应用程序。
Hang on a second, apps? Projects? What’s the difference?An app is a web application that performs some functionality. It can be a blog, a login system, or even a file server. A project is a collection of apps and configurations which together form a website.
等一下,应用程序? 项目? 有什么区别?应用程序是执行某些功能的Web应用程序。 它可以是博客, 登录系统甚至文件服务器。 项目是应用程序和配置的集合,它们共同构成一个网站。
安装Django: (Installing Django:)
The simplest way to install is with pip, the Python package manager.
最简单的安装方法是使用Python包管理器pip。
python -m pip install Django
For a full installation guide, check out Django's Official Documentation.
有关完整的安装指南,请参阅Django的官方文档 。
开始一个项目: (Starting a Project:)
Once you have Django installed, you will have access to the django-admin
tool which helps developers with setting up projects and apps and also provides other handy tools.Running django-admin startproject myproject
will create a new folder in the current directory where your project will live. It will also create many of the necessary files you will need to get going.
安装Django之后,您将可以访问django-admin
工具,该工具可帮助开发人员设置项目和应用程序,并提供其他便捷工具。运行django-admin startproject myproject
将在当前目录中创建一个新文件夹会活下去。 它还将创建许多您将需要使用的必要文件。
Here's what your directory will look like after running this command:
运行此命令后,目录如下所示:
myproject/
我的项目/
manage.py
manage.py
myproject/
我的项目/
__init__.py
__init__.py
settings.py
settings.py
urls.py
urls.py
asgi.py
asgi.py
Inside the myproject
folder you will find a manage.py
file, which is extremely useful and provides many handy utilities. There will be another folder named myproject
which will be where you set your configurations for the project. The outer myproject/ root directory is a container for your project, its name doesn’t actually matter and if you find this confusing you can rename it to anything you like.The inner myproject/ directory is the actual Python package for your project. Its name is the Python package name you’ll need to use to import anything inside it.
在myproject
文件夹中,您将找到一个manage.py
文件,该文件非常有用,并提供许多方便的实用程序。 将有另一个名为myproject
文件夹,您可以在其中设置项目的配置。 外部的myproject /根目录是项目的容器,它的名称实际上并不重要,如果您感到困惑,则可以将其重命名为您喜欢的任何名称。内部的myproject /目录是项目的实际Python包。 它的名称是Python包名称,您将需要使用它在其中导入任何内容。
The important files to note here are the myproject/settings.py
, where your Django and app specific settings are configured, and the myproject/urls.py
.
这里要注意的重要文件是myproject/settings.py
(用于配置Django和应用程序的特定设置)以及myproject/urls.py
The urls.py
file is used to create urls within your website and point them to a location to service the request. This image does a great job explaining how Django handles requests:
urls.py
文件用于在您的网站内创建URL,并将它们指向服务请求的位置。 该图像在解释Django如何处理请求方面做得很好:
Kudos to Ryan Nevius for creating such a wonderful visualization.
感谢Ryan Nevius创造了如此出色的可视化效果。
The myproject/urls.py
file outlines the URL resolution for the entire website. Each app you add to your website will contain its own urls.py
file which outlines the URL resolution within that specific app.
myproject/urls.py
文件概述了整个网站的URL解析。 您添加到网站的每个应用程序都将包含其自己的urls.py
文件,该文件概述了该特定应用程序中的URL解析。
Now that you have a grasp on what some of those files are used for, let’s dive into getting a project started with the manager script’s commands.
现在您已经了解了其中一些文件的用途,让我们开始使用Manager脚本的命令开始一个项目。
One command to note would be the startapp
command used for creating an app inside your project the same way you created the app. python manage.py startapp myapp
will create a new folder and some of the necessary files for creating a new app in your project.
要注意的一个命令是startapp
命令,用于在项目内部创建应用程序,方法与创建应用程序相同。 python manage.py startapp myapp
将创建一个新文件夹以及一些用于在项目中创建新应用的必要文件。
myapp/
myapp /
__init__.py
__init__.py
admin.py
管理员
apps.py
apps.py
migrations/
迁移/
__init__.py
__init__.py
models.py
models.py
tests.py
tests.py
The main difference here is the presence of the models and views files, which are used to define the database and the frontend functionality of the app, respectively.
这里的主要区别是模型和视图文件的存在,它们分别用于定义数据库和应用程序的前端功能。
Models are classes that define your database tables. We will discuss models in more detail later in this tutorial.
模型是定义数据库表的类。 在本教程的后面,我们将更详细地讨论模型。
Views control the frontend structure and functionality of the app taking in a web request and returning a web response. Probably the most important command to remember is the runserver command: python manage.py runserver
. This will run your project on your localhost at the default port, 8000.
视图控制应用程序的前端结构和功能,以接收Web请求并返回Web响应。 要记住的最重要的命令可能是runserver命令: python manage.py runserver
。 这将在默认端口8000的本地主机上运行项目。
That’s it! With three simple steps you will see a welcome landing page showing you that the installation worked.
而已! 通过三个简单的步骤,您将看到一个欢迎登录页面,向您显示安装成功。
There is an extremely well written tutorial in Django’s Documentation providing a far more in depth walk through of starting a project. It can be found here: Starting a Project
Django文档中有一篇写得很好的教程,它提供了有关启动项目的更深入的介绍。 可以在这里找到: 启动项目
如何建立模型 (How to set up models)
Like many other web frameworks, Django has an implementation of the object-relational mapping (ORM) concept. In Django, this implementation is called models.
像许多其他Web框架一样,Django具有对象关系映射( ORM )概念的实现。 在Django中,此实现称为模型。
Models are a very important topic to understand when developing a project in Django. In there most basic form, models can be thought of as wrappers for database tables.Said differently, a Django model is used to define your data. It contains the fields and behaviours of the data you store. Each model maps to a single table in your database and fields in your model map to fields in your database.
在Django中开发模型时,模型是一个非常重要的主题。 在最基本的形式中,模型可以看作是数据库表的包装器。换句话说,Django模型用于定义数据。 它包含您存储的数据的字段和行为。 每个模型都映射到数据库中的单个表,模型中的字段映射到数据库中的字段。
When writing models you have access to powerful built-in field types that do a lot of the heavy lifting for you. Forget writing SQL code manually to construct your database. You can simply write a model class and run the migration commands to have a fully functional SQL script loaded into your database.
编写模型时,您可以访问功能强大的内置字段类型,这些类型对您来说很繁重。 无需手动编写SQL代码即可构建数据库。 您只需编写模型类并运行迁移命令,即可将功能齐全SQL脚本加载到数据库中。
Django offers a User Model as part of its built in authentication system which allows you to ignore the backend side of all the login/sign-up and password handling.
Django提供了一个用户模型作为其内置身份验证系统的一部分,该模型允许您忽略所有登录/注册和密码处理的后端。
When designing the models for my new site I needed the following three models:
在为新站点设计模型时,我需要以下三个模型:
Profile - a wrapper class around the User model to add non-auth related information (often called a Profile Model)
Profile-User模型周围的包装器类,用于添加与非身份验证相关的信息(通常称为Profile Model )
- Course - to store all the information about each course 课程-存储有关每个课程的所有信息
Document - a model that stores information about which files are attributed to each course. I specifically wanted to upload Markdown documents, as that's how my public blog is already built
文档-一种模型,用于存储有关哪些文件归于每个课程的信息。 我特别想上传Markdown文档,因为这就是我的公共博客的建立方式
Here's an example of a model:
这是一个模型的例子:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
enrolled_courses = models.ManyToManyField(Course)
A Profile Model is a useful tool for extending the functionality of the existing user model in order to store information about the user, beyond just authentication data. In my case I created a profile model named Profile to store which courses the user is enrolled in.
配置文件模型是用于扩展现有用户模型功能的有用工具,以存储关于用户的信息,而不仅仅是身份验证数据。 在我的情况下,我创建了一个名为Profile的配置文件模型来存储用户注册的课程。
Here's my Course Model:
这是我的课程模型:
class Course(models.Model):
course_title = models.CharField(max_length=200)
course_description = models.CharField(max_length=500)
course_price = models.DecimalField(max_digits=10, decimal_places=2)
My Course model is fairly straightforward. I only needed to store 3 pieces of information about each course for logistics while the actual content of the course is handled by the Document model.
我的课程模型非常简单。 我只需要为每门课程存储3条信息以进行物流,而课程的实际内容则由Document模型处理。
class Document(models.Model):
course = models.ForeignKey(Course,on_delete=models.PROTECT)
file = models.FileField (
upload_to=markdown_upload_location,
default='default.md'
)
Here I take advantage of some built in python functionality, where I’m passing the function markdown_upload_location
into the FileField
constructor.
在这里,我利用了一些内置的python功能,即将函数markdown_upload_location
传递到FileField
构造函数中。
This function is used to determine where the file being uploaded is to be stored on the file system. Passing the function into the constructor allows the function to be run each time a new file is uploaded instead of only being run once and then the same result being used over again.
此功能用于确定要上传的文件在文件系统上的存储位置。 将函数传递到构造函数中后,每次上载新文件时都可以运行该函数,而不是只运行一次,然后再次使用相同的结果。
Essentially, when an admin (me) uploads a new course to the site, a new folder is created for that course and all markdown files for that course are stored there. The Document model records link those files to the course record in the database.
本质上,当管理员(我)将新课程上传到站点时,将为该课程创建一个新文件夹,并且该课程的所有降价文件都存储在该文件夹中。 文档模型记录将这些文件链接到数据库中的课程记录。
One thing I took away from setting up these models was how easy the process of designing my database became. Gone are the days of MySQL Workbench and ERR diagrams, or writing SQL line-by-line and executing painful updates to schemas.
我从建立这些模型中脱颖而出的一件事就是设计数据库的过程变得多么容易。 MySQL Workbench和ERR图,或者逐行编写SQL并对模式执行痛苦的更新的日子已经一去不复返了。
整合条纹支付 (Integrating Stripe Payments)
Stripe is a platform used by many websites around the world to take payment from customers. It’s secure, easy to use for customers and most importantly, it’s easy for us developers to set up!
Stripe是全球许多网站用来从客户处收款的平台。 它是安全的,易于客户使用,最重要的是,对于我们的开发人员来说,设置也很容易!
The pricing is also quite fair compared to their competition, currently sitting at 2.9% + 0.30 CAD per transaction. This pricing applies to one time payments as well as their subscription sign ups.
与他们的竞争对手相比,价格也相当合理,目前为每笔交易2.9%+ 0.30加元。 此定价适用于一次性付款及其订阅注册。
In order to use Stripe as a developer you must make an account and check out their developer pages to review the options. They have prebuilt checkouts, entire libraries and SDKs for building your own custom checkout. Stripe also provides preexisting plugins for web frameworks (Wordpress, Drupal, etc.)
为了将Stripe用作开发人员,您必须注册一个帐户并查看其开发人员页面以查看选项。 他们具有预先构建的结帐,整个库和SDK,用于构建自己的自定义结帐。 Stripe还为Web框架(Wordpress,Drupal等)提供了预先存在的插件。
I decided to use their Checkout tool which is a secure, Stripe-hosted payment page that allowed me to avoid having to build a payment page. This not only saves the time of developing the frontend page for collecting payment information, but also the hassle of securing the payment in the backend.
我决定使用他们的Checkout工具,该工具是由Stripe托管的安全付款页面,使我不必构建付款页面。 这不仅节省了开发用于收集付款信息的前端页面的时间,而且节省了在后端保护付款的麻烦。
Security is a huge topic nowadays and customers are wary of where they hand out their credit card details, so for me, using Stripe was a no brainer. I store none of the users details. Instead, they are sent straight to Stripe where they can be securely handled.
如今,安全性已成为一个重要的话题,客户对于在哪里分发信用卡详细信息会有所警惕,因此对我而言,使用Stripe毫无疑问。 我不存储任何用户详细信息。 相反,它们会直接发送到Stripe,在那里可以对其进行安全处理。
With a few lines of code I was able to import Stripe’s pre-built Javascript checkout module. Here's the script tag:
使用几行代码,我就可以导入Stripe的预构建Java Checkout模块。 这是脚本标签:
<script
src="https://checkout.stripe.com/checkout.js"
class="stripe-button"
data-key="{{ key }}"
data-description="Payment: {{ course.course_title }}"
data-amount="{% multiply course.course_price 100 %}"
data-locale="auto">
</script>
Here the data-key is set to the Stripe public key, similar to any developer API key. The description is what will appear in your Stripe dashboard for the payment received and the amount is the number of cents for the purchase. This simple inclusion imports this payment page as a modal on the website:
此处,数据密钥设置为Stripe公共密钥,类似于任何开发人员API密钥。 描述是您的Stripe仪表板中显示的已收付款的内容,金额是购买的美分数。 这种简单的包含方式将以下页面上的付款页面导入网站:
Once a customer fills out the payment information you only need to bundle up the payment information into a request and send it to Stripe. Next, Stripe is able to process the information and approve the payment within seconds.
客户填写付款信息后,您只需要将付款信息捆绑到请求中,然后将其发送到Stripe。 接下来,Stripe能够在几秒钟内处理信息并批准付款。
# Send the charge to Stripe
charge = stripe.Charge.create(
amount=amount,
currency=currency,
description=f"Payment for course: {courseTitle}", source=self.request.POST['stripeToken']
)
在EC2实例上部署新站点 (Deploying my new site on an EC2 instance)
Once I was finished developing my new site on my localhost, I needed to find a place to deploy it. I’ve had some experience with AWS and already had an account so it made for an easy decision. Amazon’s Elastic Compute Cloud - usually referred to as EC2 - allows for an abundance of configurations, I simply went with the most straightforward set up. More specifically, a Ubuntu machine running on a T2 Micro server would be ample performance for this site.
在我的本地主机上完成新站点的开发后,我需要找到一个部署它的地方。 我在AWS方面有一些经验,并且已经拥有一个帐户,因此可以轻松做出决定。 亚马逊的Elastic Compute Cloud(通常称为EC2)允许进行大量配置,我只是采用了最简单的设置。 更具体地说,在T2 Micro服务器上运行的Ubuntu计算机对于该站点而言将具有足够的性能。
Setting up the server was the easiest part of deployment, I set up a server in less than 10 minutes. Next I had to attach an elastic IP address to the instance and update my DNS records in Route53 (where my domain lives).After setting up the server I had to figure out how I was going to serve the website to visitors. I’ve had some experience in the past with Apache so that was a natural choice. It turns out that Apache and Django mesh together very well.
设置服务器是部署过程中最简单的部分,我不到10分钟即可设置服务器。 接下来,我必须在实例上附加一个弹性IP地址并在Route53 (我的域所在的地方)中更新DNS记录。设置服务器后,我必须弄清楚如何为访问者提供网站服务。 我过去在Apache上有过一些经验,所以这是很自然的选择。 事实证明,Apache和Django很好地结合在一起。
Django is served via its WSGI (Web Server Gateway Interface) - a fast CGI interface for Python, this is similar to PHP’s FPM if you are familiar with that. In simple terms, the WSGI is a layer between Django and the web server that acts as an interface to serve the web pages.
Django通过其WSGI(Web服务器网关接口)提供服务-WSGI是Python的快速CGI接口,如果您熟悉的话,它类似于PHP的FPM。 简单来说,WSGI是Django与网络服务器之间的一层,充当服务于网页的接口。
As you may already know, Python is normally run within a virtualenv
. This creates a virtual environment where the dependencies for a particular project can live without interfering with the system’s version of python.
您可能已经知道,Python通常在virtualenv
运行。 这将创建一个虚拟环境,在该虚拟环境中可以存在特定项目的依赖项,而不会干扰系统的python版本。
If you’d like to learn a bit more about virtualenv check out the Hitchhiker's Guide to Python.
如果您想了解有关virtualenv的更多信息,请查阅《 Hitchhiker的Python指南》 。
Basically this is important only to configure the Apache configurations. To serve the files correctly you need to make a WSGI Daemon for your Django project like so:
基本上,这仅对配置Apache配置很重要。 为了正确提供文件,您需要为Django项目制作一个WSGI守护程序,如下所示:
# /etc/apache2/sites-available/mysite.conf:
WSGIProcessGroup courses.nickmccullum.com
WSGIDaemonProcess course python-path=/home/ubuntu/django/courses-website python-home=/home/ubuntu/django/courses-website-venv
WSGIProcessGroup course
WSGIScriptAlias / /home/ubuntu/django/courses-website/courses-website/wsgi.py
<VirtualHost *:80>
ServerName courses.nickmccullum.com
</VirtualHost>
This tells Apache to utilize the WSGI daemon in order to properly serve the files from the Django project. Once this was set up, I needed to restart Apache, wait the 24 hours it took for the DNS records to update, then - voilà:
这告诉Apache使用WSGI守护程序来正确地提供Django项目中的文件。 设置完成后,我需要重启Apache,等待24小时更新DNS记录,然后-voilà:
One last step, I needed to secure my site with SSL (Secure Socket Layer). After all, I am asking people to make payments on my site, so customers will expect the site to be secured!
最后一步,我需要使用SSL(安全套接字层)保护我的网站。 毕竟,我要人们在我的网站上付款,所以客户希望该网站受到保护!
The simplest way to enable SSL on a site, in my opinion, is through Lets Encrypt. They offer a tool called Certbot for free, which can be enabled on your server to auto renew a server certificate and keep your server running with SSL 24/7 all year long.
我认为,在网站上启用SSL的最简单方法是通过Lets Encrypt 。 他们免费提供了一个称为Certbot的工具,可以在您的服务器上启用该工具以自动续订服务器证书,并使服务器全年保持SSL 24/7运行。
It’s as simple as the following three steps:1. Install Certbot:
只需执行以下三个步骤即可:1。 安装Certbot:
sudo apt-get install certbot python3-certbot-apache
sudo apt-get install certbot python3-certbot-apache
NOTE: This script will look at the ServerName setting in your apache configuration file to create the certificate so make sure you’ve set that before running it.
注意 :此脚本将查看apache配置文件中的ServerName设置以创建证书,因此请确保在运行它之前进行了设置。
2. Get the certificate and tell certbot to update the apache configuration automatically:
2.获取证书,并告诉certbot自动更新apache配置:
sudo certbot --apache
sudo certbot --apache
3. Test the auto renewal:
3.测试自动续订:
sudo certbot renew --dry-run
sudo certbot renew --dry-run
Once you’ve configured SSL you can test to make sure the certificate was installed correctly by checking this website: https://www.ssllabs.com/ssltest/.
配置SSL后,您可以通过检查以下网站来测试以确保证书已正确安装: https : //www.ssllabs.com/ssltest/ 。
After securing my site with SSL I opened the EC2 instance’s security rules to allow the site to be public. With my new site up and running on my EC2 instance, I am now able to securely sell my courses to customers who wish to learn about various topics in software development.
使用SSL保护我的网站后,我打开了EC2实例的安全规则以允许该网站公开。 在新站点启动并在EC2实例上运行的情况下,我现在可以将课程安全地出售给希望了解软件开发各个主题的客户。
最后的想法 (Final Thoughts)
I am grateful for all of the experience I gained throughout this project, from navigating a new web framework to integrating the Stripe API – I certainly learned a lot!
对于在整个项目中获得的所有经验,从浏览新的Web框架到集成Stripe API,我深表谢意,我当然学到了很多东西!
Learning a new topic like Django can be overwhelming but I felt their documentation was very strong compared to others that I’ve read (erhm, AWS).
学习像Django这样的新主题可能会让人不知所措,但是与其他人(erhm,AWS)相比,我觉得他们的文档非常强大。
If I were to give a single piece of advice I would tell you that the most valuable resource with any tool is the official documentation. This is especially true when it’s well written. But no matter what tool you are using, never be afraid of the docs and get used to reading them in order to find answers to your problems.
如果我只提供一个建议,我会告诉您,任何工具中最有价值的资源是官方文档。 写得好尤其如此。 但是,无论您使用哪种工具,都不要害怕文档并习惯阅读它们以找到问题的答案。
This article was written by Nick McCullum, who teaches Python, JavaScript, and Data Science courses on his website.
本文由Nick McCullum撰写,他在他的网站上教授Python , JavaScript和数据科学课程。