heroku
by Alfarhan Zahedi
通过Alfarhan Zahedi
Recently, I published my first Django application on Heroku.
最近,我在Heroku上发布了我的第一个Django应用程序。
The application is fairly simple — it lists the score associated with every classical problem on SPOJ.
该应用程序非常简单-它列出了与SPOJ上每个经典问题相关的分数。
SPOJ — Sphere Online Judge — is a problemset archive, online judge and contest hosting service accepting solutions in many languages.
SPOJ — Sphere Online Judge —是一个问题集存档,在线裁判和竞赛托管服务,接受多种语言的解决方案。
You can find the application live here.
您可以在此处找到该应用程序。
The application uses the Python libraries bs4
and requests
to scrape the contents of the aforementioned website, obtain the required details for every problem (namely — problem code, problem name, users and score), and store them in a database.
该应用程序使用Python库bs4
并requests
抓取上述网站的内容,获取每个问题所需的详细信息(即问题代码,问题名称,用户和得分 ),并将它们存储在数据库中。
Now, the score associated with the problems on SPOJ is dynamic. It is calculated using the following formula:
现在,与SPOJ上的问题相关的分数是动态的。 它使用以下公式计算:
80 / (40 + number_of_people_who_have_solved_the_problem)
80 /(40 +人数已解决的问题人数)
So, the score associated with the problems on SPOJ changes as number_of_people_who_have_solved_the_problem changes.
因此,与SPOJ上的问题相关的分数随着number_of_people_who_have_solved_the_problem 而变化 变化。
Hence, the data collected by my application will be rendered useless after a certain interval of time. I need to set up a scheduler to keep my database updated.
因此,我的应用程序收集的数据在一定时间间隔后将变得无用。 我需要设置一个调度程序以保持数据库更新。
Now, it’s a dead simple application. So I wanted to set up the scheduler with the least amount of configuration and code possible.
现在,这是一个简陋的简单应用程序。 因此,我想以尽可能少的配置和代码来设置调度程序。
Let us understand our two saviors.
让我们了解我们的两个救世主。
Custom Django Management Commands are structured as Python classes that inherit their properties and behavior from django.core.management.base.BaseCommand
class.
自定义Django管理命令的结构为Python类,这些类从django.core.management.base.BaseCommand
类继承其属性和行为。
They are used to add a manage.py
action for a Django app. runserver
or migrate
are two such actions.
它们用于为Django应用添加manage.py
操作。 runserver
或migrate
是两个这样的操作。
A typical example of such a class would be:
此类的典型示例是:
from django.core.management.base import BaseCommand
class Command(BaseCommand): help = "" def handle(self, *args, **options): self.stdout.write("Hello, World!")
The class must be named Command
, and subclass BaseCommand
.
该类必须命名为Command
,并且必须命名为BaseCommand
。
help
should hold a short description of the command, which will be printed in help messages.
help
应该包含命令的简短描述,该描述将显示在帮助消息中。
handle(self, *args, **options)
defines the actual logic of the command. In this case, we are just writing the string Hello, World!
into the standard output. In my case, handle(self, *args, **options)
performs the task of scraping the website — spoj.com and updating the database if the score associated with any of the problem changes.
handle(self, *args, **options)
定义命令的实际逻辑。 在这种情况下,我们只是写字符串Hello, World!
进入标准输出。 以我为例 , handle(self, *args, **options)
执行抓取网站spoj.com的任务,如果与任何问题相关的分数发生变化,则更新数据库。
handle(self, *args, **options)
is automatically run whenever the following command is used:
每当使用以下命令时handle(self, *args, **options)
都会自动运行:
python manage.py
python manage.py
If the name of the script is, say, script.py
, then the command would be:
如果脚本的名称为script.py
,则命令为:
python manage.py script
python manage.py script
Notice the handle method declares three input argument: self
to reference the class instance, *args
to reference arguments of the method itself, and **option
to reference arguments passed as part of the management command.
注意handle方法声明了三个输入参数: self
引用类实例, *args
引用方法本身的参数, **option
引用作为管理命令一部分传递的引用参数。
Where in the project structure does this script.py
go?
这个script.py
在项目结构中的哪个位置?
(Here, script.py
refers to the name of the script containing the custom Django management command.)
(在这里, script.py
是指包含自定义Django管理命令的脚本的名称。)
It’s quite simple. The official documentation explains it well:
这很简单。 官方文档对此进行了很好的解释:
Just add a
management/commands
directory to the application. Django will register amanage.py
command for each Python module in that directory whose name doesn’t begin with an underscore.只需将
management/commands
目录添加到应用程序即可。 Django将为该目录中每个名称都不以下划线开头的Python模块注册一个manage.py
命令。
For example:
例如:
polls/ __init__.py models.py management/ __init__.py commands/ __init__.py _private.py closepoll.py tests.py views.py
In this example, the
closepoll
command will be made available to any project that includes thepolls
application inINSTALLED_APPS
.在此示例中,
closepoll
命令将对包含INSTALLED_APPS
的polls
应用程序的任何项目可用。
The
_private.py
module will not be available as a management command.
_private.py
模块将不能作为管理命令使用。
The
closepoll.py
module has only one requirement – it must define a classCommand
that extendsBaseCommand
or one of its subclasses.
closepoll.py
模块只有一个要求–它必须定义一个扩展BaseCommand
或其子类之一的Command
类 。
And so, if we run the following command in our terminal:
因此,如果我们在终端中运行以下命令:
python manage.py closepoll
,
python manage.py closepoll
,
handle(self, *args, **options)
insideclosepoll.py
will be run, and any logic/tasks contained inside the aforementioned function will be executed.
closepoll.py
handle(self, *args, **options)
将被运行,并且上述函数中包含的任何逻辑/任务都将被执行。
My project structure is as follows:
我的项目结构如下:
spojscore│ .gitignore│ manage.py│ Procfile│ README.md│ requirements.txt│ runtime.txt│├───core│ │ admin.py│ │ apps.py│ │ models.py│ │ tests.py│ │ views.py│ │ __init__.py│ ││ ├───management│ │ │ __init__.py│ │ ││ │ ├───commands│ │ script.py│ │ __init__.py│ │ │ ││ ├───static│ │ └───core│ │ ├───css│ │ │ style.css│ │ ││ │ └───img│ │ favicon.png│ │ logo.png│ ││ ├───templates│ └───core│ core.html│└───spojscore settings.py urls.py wsgi.py __init__.py
Here, script.py
contains the custom management command — Python code to scrape spoj.com, collect details of all the classical problems, and update the database accordingly.
在这里, script.py
包含自定义管理命令-刮spoj.com的 Python代码,收集所有经典文件的详细信息 问题,并相应地更新数据库。
If you see, it’s situated inside core\management\commands
.
如果看到的话,它位于core\management\commands
内部。
If you are interested, you can find script.py
here.
如果您有兴趣,可以在此处找到script.py
。
I think its clear now that I can scrape spoj.com and obtain the desired data by simply running python manage.py script
from the terminal.
我认为现在很清楚,我可以通过从终端运行python manage.py script
来抓取spoj.com并获取所需的数据。
So, to keep my database updated, I just need to run the above command at least once a day.
因此,要保持数据库更新,我只需要每天至少运行一次以上命令。
As per Heroku’s website:
根据Heroku的网站 :
Scheduler is a free add-on for running jobs on your app at scheduled time intervals, much like
cron
in a traditional server environment.Scheduler 是一个免费插件,可以按计划的时间间隔在您的应用程序上运行作业,就像在传统服务器环境中使用
cron
一样。
A dashboard allows you to configure jobs to run every 10 minutes, every hour, or every day, at a specified time. When invoked, these jobs will run as one-off dynos and show up in your logs as a dyno named like
scheduler.X
.仪表板使您可以配置作业,使其在指定时间每10分钟,每小时或每天运行一次。 调用这些作业时,它们将作为一次性dynos运行,并在日志中显示为名称为
scheduler.X
的dyno。
Once you’ve deploying the application, install the Heroku Scheduler add-on.
部署应用程序后,请安装Heroku Scheduler加载项。
To schedule a frequency and time for a job, open the Heroku Scheduler dashboard by finding the app in My Apps, clicking “Overview”, then selecting “Heroku Scheduler” from the Installed add-ons list.
要计划工作的频率和时间,请在“ 我的应用程序”中找到该应用程序 ,然后单击“概述”,然后从“已安装的加载项”列表中选择“ Heroku Scheduler”,以打开Heroku Scheduler仪表板。
On the Scheduler Dashboard, click “Add Job…”, enter a task, select a frequency, dyno size, and next run time.
在“调度程序仪表板”上,单击“添加作业…”,输入任务,选择频率,功率大小和下一次运行时间。
In my case, the task is python manage.py script
, which is to be executed daily (frequency) using my free dynos (dyno size) at 00:00 UTC (next run time).
在我的情况下,任务是python manage.py script
,它将使用我的免费dynos(dyno大小)在世界标准时间00:00(下一次运行时间)每天(频率)执行。
That’s it!
而已!
My database will be updated at 00:00 UTC every day, and I didn’t have to install any extra Python libraries, or write any extra pieces of code. Yay!
我的数据库每天都会在世界标准时间00:00进行更新,而我不必安装任何额外的Python库或编写任何额外的代码段。 好极了!
If you get stuck anywhere, drop a comment and I will try my best to help you.
如果您在任何地方卡住,请发表评论,我会尽力为您提供帮助。
Heroku’s official website says that — “Scheduler job execution is expected but not guaranteed. Scheduler is known to occasionally (but rarely) miss the execution of scheduled jobs. If scheduled jobs are a critical component of your application, it is recommended to run a custom clock process instead for more reliability, control, and visibility.” This point should be kept in mind while using Heroku Scheduler.
Heroku的官方网站说: “计划执行作业,但不能保证。 已知调度程序偶尔(但很少)会错过调度作业的执行。 如果计划的作业是应用程序的关键组成部分, 建议改为 运行自定义时钟过程,以提高可靠性,控制力和可视性。” 使用Heroku Scheduler时应牢记这一点。
Mine is dead simple application which uses the Heroku Scheduler to run a simple script just once a day. So, I guess it would do a great job!
我的是一个简单的简单应用程序,它每天使用Heroku Scheduler运行一次简单脚本。 所以,我想这会做的很棒!
My application, I suppose, is useful for competitive programmers. Why? I have explained it in great detail here.
我想我的应用程序对于有竞争力的程序员很有用。 为什么? 我在这里已经详细解释了 。
You can find the source code of my application here.
您可以在此处找到我的应用程序的源代码。
I am just another self-taught programmer.
我只是另一个自学成才的程序员。
I have being writing code for a couple of years now, and have always wanted to write about my experiences, endeavors, failures and successes.
我已经写了几年代码了,一直想写自己的经历,努力,失败和成功。
But alas, I could not.
但是a,我不能。
I thought that my endeavors were not exciting enough or that my experiences were not going to help anyone. And so I restrained myself from writing about them.
我以为自己的努力不够激动,或者我的经历不会帮助任何人。 因此,我限制自己写关于它们的文章。
To be honest, I think the same now.
老实说,我现在也一样。
So, how come I wrote this article?
那么,我怎么写这篇文章呢?
Well, this is going to be my first of many articles.
好吧,这将是我的许多文章中的第一篇。
And the reason for the change, you ask?
你问的原因是什么?
A newsletter.
时事通讯。
Last week, as usual, I received the weekly newsletter from CSS-Tricks — “This week in Web Design and Development”.
像往常一样,上周,我收到了来自CSS-Tricks的每周时事通讯- “本周的Web设计和开发” 。
Here, is an excerpt from the same:
这是同一节录的摘录:
It’s buck wild to have so many helpful resources available to help us at any moment: from blog posts and books to random node.js conference talks that only have 8 views and 7 of them are now mine. So I think this weekend has reinforced my faith in blogging and sharing what you know, where random notes left on some developer’s old blog have helped me tremendously.
随时都有如此多的有用资源可以为我们提供帮助是不受欢迎的:从博客文章和书籍到随机的node.js会议演讲,只有8个视图,其中有7个是我的。 因此,我认为这个周末加强了我对博客和分享您所知的信念,在一些开发人员的旧博客上留下的随机注释对我有很大帮助。
Anywho, on a similar note, I’ve been thinking a bunch about how social networks prioritize fame over value. If you publish something on Medium for example and it only gets a single clap then it makes you feel like, why bother? What’s the point if no-one’s reading this thing? But I think we have to fight that inclination to be woo’d with fame and social-network notoriety because I wonder how many helpful blog posts and videos weren’t made simply because someone thought they weren’t going to get half a million likes or retweets from it.
类似地,任何人,我一直在思考社交网络如何将名誉置于价值之上。 例如,如果您在Medium上发布内容,并且只有一次掌声,那么您会觉得, 为什么要打扰 ? 如果没人读这个东西有什么意义? 但是我认为我们必须与这种名望和社交网络臭名昭著相抗衡,因为我想知道有多少有用的博客文章和视频不是仅仅因为有人认为他们不会获得五十万个喜欢而被制作的吗?或从中转发。
My advice after learning from so many helpful people this weekend is this: if you’re thinking of writing something that explains something you struggled with, do it! Don’t worry about the views and likes and Internet hugs. If you’ve struggled with figuring out this one weird thing then jot it down, even if it’s unedited and it uses too many commas and you don’t like the tone of it.
在本周末从众多乐于助人的人士那里学习后,我的建议是:如果您正在考虑写一些可以解释自己所遇到的困难的东西,那就去做吧! 不用担心观点和喜欢以及互联网的拥抱。 如果您想弄清楚这件奇怪的事情,那就把它记下来,即使它未经编辑并且使用了太多逗号,您也不喜欢它的基调。
That’s because someone like me is bound to find what you’ve written and it’ll make their whole weekend a lot less stressful than it could’ve been.
那是因为像我这样的人注定会找到你所写的东西,这将使他们整个周末的压力大大减轻。
That’s it. Those few lines inspired me to write about my endeavors and experiences.
而已。 那几行启发了我写自己的努力和经历。
Maybe, you should too.
也许,你也应该。
翻译自: https://www.freecodecamp.org/news/scheduling-jobs-in-a-django-application-using-heroku-scheduler-13c971a22979/
heroku