Я помешана на продуктивности. Раньше я следила за выполнением своих задач каждый день с помощью ручки и бумаги. Затем, когда задачи стали более сложными, я начала записывать их в электронную таблицу. Так продолжалось в течение месяца, но потом я потеряла мотивацию. Мне нужен был толчок, чтобы следовать своему распорядку. Вот тут-то и появляется график вклада.
Если вы пользуетесь GitHub, то видели в своем профиле тепловую карту, которая показывает ваши вклады (коммиты, пулл-реквесты и т.д.) за каждый день в году, как продемонстрировано на рисунке выше. Я работала над проектом каждый день, чтобы поддерживать непрерывную полосу в GitHub, и все время ненавидела этот серый квадрат в своем профиле! Мне попадался туториал по созданию графика вклада с помощью Node.JS, но я предпочитаю Python, и поэтому сделала то же самое, используя Flask и Google Sheets API.
В этом руководстве я пройду пошагово через все этапы, начиная от создания приложения и заканчивая его развертыванием на Heroku. Я также поделюсь найденными мной ошибками и их решениями.
Давайте начнем с создания среды для работы над проектом. Я предполагаю, что вы уже установили Python (желательно Python 3) и pip в свою систему. В противном случае загрузите Python отсюда и следуйте инструкциям. Pip — это менеджер пакетов для Python, который помогает устанавливать дополнительные библиотеки и зависимости, необходимые для вашего приложения. Проверьте, установлен ли pip с помощью этой команды в командной строке: pip — version
.
pip install virtualenv
.pip install virtualenvwrapper-win
. (Примечание: эта команда предназначена только для Windows).mkvirtualenv your-env-name
.workon your-new-name
и деактивировать ее с помощью deactivate
.pip install flask
.Давайте теперь перейдем к созданию электронной таблицы, которая будет выступать в качестве базы данных. На мою таблицу можно взглянуть здесь (необходимо запросить доступ).
В этой таблице есть четыре поля:
Date
(Дата). У меня это поле отформатировано так же, как и в GitHub, и вы можете отформатировать его так, как захочется вам.Task
(Задача). В этом поле содержится название каждой задачи и ее описание (необязательно).Number of Tasks
(Число задач). Здесь содержится количество задач.Level
(Уровень). Здесь используется формула =IF(C2=0,”0", if(C2<=2,”1", if(C2<=4,”2",”3")))
для расчета уровня на основе количества задач. Вся колонка заполняется, исходя из этой формулы.Вы можете настроить поля по своему усмотрению, но у вас должно быть хотя бы одно поле, схожее с полем “Уровень”, потому что оно используется для определения цвета, которым заполняется каждый квадрат в графике.
Этот шаг критически важен, поскольку он позволяет нашему приложению подключаться к Google Sheets:
Client_Secret.json
.Insufficient Permission
.Client_Secret.json
будет client_email
. Скопируйте этот e-mail, вставьте его в всплывающее окно и нажмите “Отправить”.Вот и всё! Теперь давайте извлечем данные из электронной таблицы и отобразим их в нашем приложении.
Contribution Graph
|--Static
|--CSS
|--design.css
client_secret.json
|--templates
|--index.html
|--app.py
|--spreadsheet.py
|--Procfile
|--requirements.txt
Не волнуйтесь! Я объясню, для чего нужен каждый файл и какую задачу он выполняет, по ходу дела. Этот пример нужен для того, чтобы дать вам примерное представление о том, как здесь структурированы папки.
Теперь давайте посмотрим, можем ли мы получить доступ к данным из нашей таблицы. Существует популярный Python API под названием gspread
, который позволяет легко читать (и записывать) из Google Sheets и Oauth, а также дает вашему приложению вызывать Google API от имени учетной записи сервиса. Установите gspread
и oauth2
с помощью pip — pip install gspread oauth2
.
Файл JSON расположен в папке Static
(здесь хранятся все статические файлы, которые не изменяются, такие как CSS и JS), поэтому получите к нему доступ из корня с помощью модуля os — os.path.realpath(os.path.dirname(__file__))
. Затем создайте переменную scope
, содержащую ссылку на фид на диске, и переменную creds
для доступа к файлу JSON с использованием учетных данных сервиса.
Теперь вы можете получить доступ к таблице, используя client.open(‘Daily Contribution’).sheet1
, где Daily Contribution
— это имя файла, а sheet1
— имя первой таблицы. Мы будем хранить значения каждого столбца в переменной и создадим общую переменную data
, которая содержит их все, присваивая возвращаемому значению функции getData()
, как показано в коде ниже:
import os
import gspread
from oauth2client.service_account import ServiceAccountCredentials
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
json_file = os.path.join(SITE_ROOT,'static', 'Client_Secret.json')
scope = ['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name(json_file, scope)
client = gspread.authorize(creds)
sheet = client.open('Daily Contribution').sheet1
def getData():
date = sheet.col_values(1, value_render_option='FORMATTED_VALUE')
task = sheet.col_values(2, value_render_option='FORMATTED_VALUE')
numberOfTasks = sheet.col_values(3, value_render_option='FORMATTED_VALUE')
level = sheet.col_values(4, value_render_option='FORMATTED_VALUE')
data = [date, task, level]
return data
Чтобы убедиться, что все работает как надо, вы можете вывести data
в командной строке, воспользовавшись python spreadsheet.py
.
Данные для нашего приложения уже готовы. А теперь давайте сделаем его красивым!
Создайте файл index.html
и поместите его в папку “templates”. Flask в общем случае ищет HTML-файлы внутри этой папки, поскольку он использует библиотеку шаблонов Jinja для отрисовки шаблонов.
<!DOCTYPE html>
<html>
<head>
<title>Contribution Graph</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/design.css') }}" />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lemonada:[email protected];400&display=swap" rel="stylesheet">
</head>
<body>
<h1>My Daily Contribution Graph</h1>
<div class="graph">
<ul class="months">
<li>Jan</li>
<li>Feb</li>
<li>Mar</li>
<li>Apr</li>
<li>May</li>
<li>Jun</li>
<li>Jul</li>
<li>Aug</li>
<li>Sep</li>
<li>Oct</li>
<li>Nov</li>
<li>Dec</li>
</ul>
<ul class="days">
<li>Sun</li>
<li>Mon</li>
<li>Tue</li>
<li>Wed</li>
<li>Thu</li>
<li>Fri</li>
<li>Sat</li>
</ul>
<ul class="squares">
{% for i in range(1,366) %}
{% if data[1][i] %}
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="{{data[1][i]}} on {{data[0][i]}}" data-level="{{data[2][i]}}"></li>
{% else %}
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="No Contribution on {{data[0][i]}}" data-level="{{data[2][i]}}"></li>
{% endif %}
{% endfor %}
</ul>
</div>
<div class="contributeLegend">
<p class="legendTitle">Legend</p>
<ul class="legendSquares">
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="No Contribution"></li>
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="Less than 2 Contributions" data-level="1"></li>
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="Less than 4 Contributions" data-level="2"></li>
<li data-toggle="tooltip" data-placement="bottom" data-animation="false" delay="0" title="More than 4 Contributions" data-level="3"></li>
</ul>
</div>
<script>
var squares = document.querySelector(".squares")
</script>
</body>
</html>
Что касается CSS, то я находила туториал, который сэкономил мне время, однако вы можете реализовать его так, как захочется именно вам.
Я также создала систему условных обозначений, включая всплывающие подсказки, и изменила цвет квадратов на розовый. Вы также можете изменять внешний вид приложения по своим предпочтениям!
Создайте промежуточный файл, который отправляет данные в HTML-файлы, под названием app.py
. Импортируйте spreadsheet.py
и присвойте переменной значение, возвращаемое функцией getData()
. Передайте переменную в функцию render_template()
вместе с HTML-кодом.
from flask import Flask, render_template, json
import spreadsheet
app = Flask(__name__)
@app.route("/")
def main():
data = spreadsheet.getData()
return render_template('index.html', data=data)
if __name__ == "__main__":
app.jinja_env.auto_reload = True
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.run(host="0.0.0.0", port=5000, threaded=True)
Код в блоке if
автоматически перезагружает содержимое приложения всякий раз, когда в него вносятся изменения.
Теперь запустите приложение из командной строки, используя команду python app.py
(убедитесь, что вы активировали виртуальную среду). Если все пройдет хорошо, ваше приложение запустится и будет работать в localhost http://127.0.0.1:5000/
!
Использование Heroku требует, чтобы у вас был установлен Git.
Heroku --version
.Heroku login -i
и введя свои учетные данные.gunicorn
для развертывания нашего приложения, поскольку он относительно быстрый и может обрабатывать несколько запросов одновременно. Установите его с помощью команды pip install gunicorn
.requirements.txt
, который информирует Heroku о зависимостях для нашего приложения, набрав pip freeze > requirements.txt
.web: gunicorn --bind 0.0.0.0:$PORT app:app
. Назовите его Procfile
. (Примечание: не используйте никаких расширений). Procfile
сообщает Heroku, какие команды будут выполняться приложением при запуске.app:app
первое app
отсылается к имени файла (к примеру, app.py
), а второе app
отсылается к app = Flask(__name__)
. H14 error: no web processes running
, но мне удалось избавиться от нее с помощью следующей команды: heroku ps:scale web=1
. Она информирует Heroku, что мы не запускаем никаких веб-Dyno. Если вы не поняли, о чем речь, отлично — продолжайте дальше.git init
.git add .
и сделайте коммит git commit -m "Initial Commit"
.heroku create
, что генерирует ссылку для вашего приложения и URL-адрес удаленного репозитория, а затем введите команду heroku open
, которая откроет приложение в вашем браузере.git remote add heroku 'repo-link-generated-on-heroku-create'
.git push heroku master
.Ваше приложение теперь работает в интернете!
Здесь можно посмотреть мой вариант.
Также вы можете просмотреть мои итоговые файлы на GitHub.
Перевод статьи Padhma Sahithya: Recreate GitHub’s Contribution Graph Using Flask and Google Sheets
Комментарии