Windows task manager python

Provide feedback

Saved searches

Use saved searches to filter your results more quickly

Sign up

Пройдите тест, узнайте какой профессии подходите

Изучите, как использовать Python для работы с планировщиком задач в операционной системе Windows с помощью библиотеки `schedule`.

Python является мощным инструментом для автоматизации и управления различными задачами на вашем компьютере. В этой статье мы рассмотрим, как использовать Python для работы с планировщиком задач на примере операционной системы Windows.

Освойте Python на курсе от Skypro. Вас ждут 400 часов обучения и практики (достаточно десяти часов в неделю), подготовка проектов для портфолио, индивидуальная проверка домашних заданий и помощь опытных наставников. Получится, даже если у вас нет опыта в IT.

Планировщик задач Windows

Планировщик задач Windows позволяет автоматически запускать программы или скрипты по расписанию. Это полезно для выполнения рутинных задач, таких как резервное копирование данных, обновление баз данных или отправка отчетов.

Библиотека schedule

Для работы с планировщиком задач в Python можно использовать стороннюю библиотеку schedule. Она предоставляет простой и удобный интерфейс для управления расписаниями.

Для установки библиотеки используйте команду:

pip install schedule

Создание задачи

Для создания задачи с использованием библиотеки schedule, выполните следующие шаги:

  1. Импортируйте библиотеку schedule.
  2. Определите функцию, которая будет выполняться по расписанию.
  3. Используйте метод schedule.every() для задания интервала выполнения функции.
  4. Используйте метод schedule.run_pending() в цикле, чтобы проверять и выполнять запланированные задачи.

Ниже приведен пример скрипта, который выполняет функцию hello_world() каждые 10 секунд:

import schedule
import time

def hello_world():
    print("Hello, World!")

schedule.every(10).seconds.do(hello_world)

while True:
    schedule.run_pending()
    time.sleep(1)

Расширенные возможности планирования

Библиотека schedule предоставляет различные методы для более гибкого планирования задач. Некоторые из них:

  • every(interval).seconds
  • every(interval).minutes
  • every(interval).hours
  • every().day.at(time)
  • every().monday.at(time)
  • every().wednesday.at(time)
  • every().friday.at(time)

Пример задачи, выполняющейся каждый день в 10:00:

import schedule
import time

def daily_task():
    print("Running daily task")

schedule.every().day.at("10:00").do(daily_task)

while True:
    schedule.run_pending()
    time.sleep(1)

Изучайте Python на онлайн-курсе от Skypro «Python-разработчик». Программа рассчитана на новичков без опыта программирования и технического образования. Курс проходит в формате записанных коротких видеолекций. Будет много проверочных заданий и мастер-классов. В конце каждой недели — живая встреча с экспертами в разработке для ответов на вопросы и разбора домашек.

Заключение

Использование Python для работы с планировщиком задач позволяет легко и быстро автоматизировать рутинные процессы на вашем компьютере. Библиотека schedule предоставляет простой и удобный интерфейс для создания и управления задачами. Вам также могут быть интересны другие возможности этой библиотеки, такие как условное выполнение задач или планирование задач с использованием крон-выражений. Удачи в изучении Python! 🐍

Уровень сложностиСредний

Время на прочтение18 мин

Количество просмотров8.1K

Привет, Хабр!

На связи участник профессионального сообщества NTA Владислав Рулев.

Это первый пост в серии, где я буду рассказывать, как создавал свой собственный task manager. В настоящее время используются различные инструменты для управления задачами, от электронной почты и Excel‑таблиц до специальных программ. Первый подход — письма и таблички, затрудняет отслеживание статуса задач, распределение ресурсов и общую координацию работ. Второй — готовое решение, имеет как плюсы, так и минусы. Подробно сильные и слабые стороны доступных на рынке task‑менеджеров разобраны тут.

Разработка собственного инструмента даст мне:

  1. Централизованное управление задачами.

    Можно вести все задачи в одном месте, что облегчит их отслеживание, приоритизацию и распределение между сотрудниками. Каждый пользователь сможет видеть свои назначенные задачи и отслеживать их статус.

  2. Анализ производительности.

    Позволит собирать данные о выполнении задач, времени, затраченном на каждую задачу, и других метриках производительности. Так инструмент поможет анализировать эффективность работы, выявлять узкие места и принимать меры для их устранения.

Навигация по посту

  • Выбор инструментов

  • Создание страницы «Авторизация»

  • Создание страницы «Профиль»

  • Создание страницы «Создание задачи»

  • Создание страниц просмотра задач

  • Планируемые доработки

  • Заключение

Выбор инструментов

Первым делом нужно определиться как конечный пользователь будет взаимодействовать с продуктом, а также какие тонкости стоит учесть:

1. Интуитивно понятный интерфейс.

Нужно создать инструмент, использовать который может каждый, вне зависимости от уровня знаний.  

2. Наличие единого шаблона создания задачи.

Так можно сократить время создания задачи путём добавления выпадающих списков с готовыми данными. Пользователю останется лишь выбрать предложенные варианты и написать описание задачи.

Опираясь на требования к разработке рассмотрю варианты реализации инструмента:

  • пошаговый скрипт в Jupyter Notebook;

  • web-приложение.

Изначально была идея сделать приложение в Jupyter Notebook используя для отрисовки интерфейса библиотеку ipywidgets, но из-за того, что на имеющейся версии библиотеки не получилось бы реализовать весь задуманный функционал, то фокус сместился на создание своего сайта.

С точки зрения пользователя сайт легче запустить и использовать, чем Jupyter Notebook, а с точки зрения разработки можно реализовать любой дизайн и почти неограниченный функционал.

Следующим шагом после определения вида задачника, будет выбор инструментов. Так как у всех сотрудников установлен python, то и разработка будет вестись на нём. На старте использовать буду следующие библиотеки:

  • Flask — легкий и гибкий фреймворк для разработки веб‑приложений;

  • Flask‑WTF — расширение Flask, интегрирующее библиотеку WTForms, которая предоставляет полезные функции для простого создания и обработки форм в веб‑приложении;

  • Psycopg2 — адаптер базы данных PostgreSQL для Python, т.к. использую Greenplum;

  • Pandas — программная библиотека для обработки и анализа данных.

Для создания первой версии такого набора инструментов хватит.

Создание страницы «Авторизация»

Для начала разработки нужно установить основные библиотеки:

$ pip install flask       
$ pip install flask-wtf
$ pip install pandas
$ pip install psycopg2

Отлично, теперь есть необходимые библиотеки для разработки веб‑приложения, пора создавать проект в PyCharm’е и поднимать локальный сервер. Структура проекта на начальном этапе должна выглядеть так.

Далее в файлы заполняются следующим образом:

Код файла __init__.py

from flask import Flask
app = Flask(name)
from app import routes

Код файла routes.py

from app import app

@app.route('/')
@app.route('/index')
def login():
    return ('Hello, World!')

Немного разберёмся что же делают декораторы @app.route. В данном случае декоратор создаёт связь между URL‑адресом, заданным в качестве аргумента, и функцией, которая написана ниже. Таким образом, когда браузер будет запрашивать адрес «/» или «/index», Flask выполнит функцию ниже и передаст обратно в браузер возвращаемое значение.

Код файла startup.py

from app import app


if __name__ == '__main__':
    app.run()

Запущу проект и перейду на указанный локальный сервер.

Сервер поднялся, теперь создам форму для авторизации. Для этого и была установлена библиотека Flask‑WTF.

В данный момент приложение простое и сильно беспокоится о конфигурации не требуется, но всё же стоит поставить секретный ключ. Для этого создам config в корневой директории приложения, а также обновлю __init__.py

Код файла config.py

import os

class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'never-gonna-give-you-up'

Flask и некоторые его расширения используют значение секретного колюча в качестве криптографического ключа, который требуется для генерации подписей и токенов. Конкретно расширение Flask-WTF использует секретный ключ для защиты веб-формы от атаки Cross-Site Request Forgery (подделка межсайтовых запросов).

Важно: при развертывании данного приложения на сервере нужно будет устанавливать уникальное и трудно подбираемое значение. Секретный ключ должен знать только доверенный круг лиц, которые сопровождают приложение!

Код файла __init__.py

from flask import Flask
from config import Config

app = Flask(__name__)
app.config.from_object(Config)

from app import routes

Мне понадобилось создать ещё один файл и заполнить его следующим образом.

Код файла forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField 
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Войти')
  • StringField – поле ввода текста, в HTML равно тегу <input type=”text”>;

  • PasswordField – поле ввода пароля, в HTML равно тегу <input type=”password”>;

  • SubmitField – кнопка отправки формы на сервер, в HTML равно тегу <input type=”submit”>.

Теперь нужно создать html страничку, куда будут передаваться переменные.

Код файла index.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='my_style.css' )}}">
    <link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='style.css' )}}">
    <title>Задачник ОАРБ - Авторизация</title>
</head>
<style>
</style>
<body>
    <div class="authorization position-absolute top-50 start-50 translate-middle">
        <div class="position-absolute top-50 start-50 translate-middle">
            <h1>Авторизация</h1><br>
            <form action="" method="post" novalidate>
                {{ form.hidden_tag() }}
                <p>
                    {{ form.username(size=32, placeholder="login") }}<br>
                    {% for error in form.username.errors %}
                    <span style="color: red;">[{{ error }}]</span>
                    {% endfor %}
                </p>
                <p>
                    {{ form.password(size=32, placeholder="password") }}<br>
                    {% for error in form.password.errors %}
                    <span style="color: red;">[{{ error }}]</span>
                    {% endfor %}
                </p>
                <p style="color: red">{{ form.error_connect.label }}</p>
                <p>{{ form.submit() }}</p>
            </form>
        </div>
    </div>
</body>
</html>

После этого доработаю файл routes следующим образом:

Код файла routes.py

from flask import render_template, redirect 

from app import app
from app.forms import LoginForm

@app.route('/')
@app.route('/index')
def login():
    form = LoginForm()
    return render_template('index.html', form=form)

Стартовая страница выглядит так:

Создание страницы «Профиль»

После того, как я сверстал форму, нужно настроить подключение к БД. Для подключения буду использовать библиотеку psycopg2, а для обработки и хранения возьму pandas.

Импортирую библиотеки:

import pandas as pd
import psycopg2 as pg

Создам метод для подключения к БД:

Код файла routes.py

# Функция подключения к БД Greenplum
def get_db_connection(user, password):
    try:
        # Переменные для глобального использования
        global user_login
        global user_password
        user_login = user
        user_password = password
        
	# Указываем параметры подключения
        conn_param = f'host=server.ru port=1234 dbname=mydb user={user} password={password}'
        
        # Создаем подключение и включаем автокомит
        conn = pg.connect(conn_param)
        conn.autocommit = True

        return conn
    except pg.OperationalError:
	# В случае ошибки выводим сообщение
        print("EGOOOOOOOOOOOOOOOOOOOR:", pg.OperationalError)
        return 0

Обновляю метод login:

@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def login():
    # Создам форму, которую буду передавать для отрисовки
    form = LoginForm()
    # Если нажали кнопку
    if form.validate_on_submit():
	# Создам подключение
        global conn
	
	# form.username.data – логин с формы
	# form.password.data – пароль с формы
        conn = get_db_connection(str(form.username.data), str(form.password.data))

	# Если подключение успешно создано
        if conn:
            return redirect('/main')
    return render_template('index.html', form=form)

Чуть подробнее остановлюсь на этом моменте.

В дизайнере маршрутов я добавил аргумент methods. Этим аргументом я показываю, что функция принимает запросы GET и POST (по умолчанию принимаются только GET запросы).

GET‑запросы — это запросы, которые возвращают информацию клиенту (в моем случае — страница в веб‑браузере).

POST‑запросы — это запросы, которые используются при отправке браузером формы на сервер (на примере данной страницы будут отправлены значения с полей ввода логина и пароля).

Рассмотрю метод form.validate_on_submit(). Данный метод выполняет обработку формы (POST‑запрос). Когда пользователь только попадает на страницу, то отправляется GET‑запрос и метод возвращает значение False, поэтому конструкция if пропускается, и пользователь видит стартовую страницу.

Когда браузер отправляет POST‑запрос (после нажатия кнопки submit), метод собирает данные с формы, запускает валидаторы, которые я создал для полей, и если всё нормально, то возвращает True.

Проработаю следующую страницу «Профиль», на которую пользователь будет попадать после аутентификации, но для начала создам шаблон, по которому будут строиться дальнейшие странички.

Механизм шаблонов Jinja2 поставляется в комплекте с Flask. Jinja2 заменяет блоки {{…}} соответствующими значениями, заданными аргументами, указанными при вызове функции render_template().

Для чего же нужен шаблонизатор?

1. Сокращение лишней работы.

Вместо того, чтобы для каждой страницы заново писать одну и ту же повторяющуюся структуру (Тег head и header), напишу её один раз, динамически изменяя только основное содержимое страницы.

2. Удобная корректировка.

Если я решу внести какие-либо изменения в структуру или стиль страницы, то нужно будет изменить только один файл (например: добавление нового элемента навигации).

3. Разделение логики и дизайна.

При помощи макета можно отдельно работать с поведением сайта и его визуальной составляющей. Это особенно удобно, если работать в паре «дизайнер-программист».

С плюсами использования шаблонизатора я разобрался, теперь создам файл base.html, который будет выглядеть следующим образом:

Код файла base.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='my_style.css' )}}">
    <title>Задачник  - {% block title %}{% endblock %}</title>
</head>
<header>
    <ul class="nav nav-pills nav-fill">
        <li class="nav-item">
            <a class="nav-link" href="/main">Профиль</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="/create_task">Создание задачи</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="/select_task_for_me">Просмотр задач для меня</a>
        </li>
        <li>
            <a class="nav-link" href="/select_task_from_me">Просмотр задач, которые назначил я</a>
        </li>
    </ul>
</header>
<body>
    {% block content_h1 %}{% endblock %}
    <hr>
    {% block content %}{% endblock %}
    <hr>
</body>
</html>

{% block … %} {% endblock %} – шаблон, куда из другого файла будет вставляться контент.

Отдельное внимание стоит уделить подключению css файла (блок <link>).

Для того, чтобы сервер мог получить css была создана структура проекта .

Файл my_style.css содержит немного доработанную выгрузку bootstrap. Bootstrap понадобился мне для создания адаптивной верстки, чтобы приложение работало хорошо при разном разрешении экрана.

Теперь создаю страницу «Профиль» следующим образом:

Код файла main.html

{% extends "base.html" %}

{% block title %}Профиль{% endblock %}

{% block content_h1 %}
<h1 style="text-align:center">Профиль</h1>
{% endblock %}

{% block content %}
    <p><b>login:</b> {{selected.iloc[0]['user_id']}} </p>
    <p><b>ФИО:</b> {{selected.iloc[0]['login']}} </p>
    <p><b>email:</b> {{selected.iloc[0]['email']}} </p>
{% endblock %}

{% extends «base.html»%} — использование созданного шаблона.

{% block …%} {% endblock%} — все теги, написанные внутри такой конструкции, подставятся в шаблон.

{{ … }} — использование переданного объекта. В данном случае я передаю Data Frame selected.

Но как получить данные для профиля? — Написать метод с запросом к БД. Выглядеть метод будет так:

Код файла routes.py

# Выборка данных о пользователе
def select_profile(connect,created_user):
    global user_login
    SQL=f'''select *
        from tm_schema.task_manager_user
        where user_id={user_login}
        '''.format(created_user)
    return pd.read_sql_query(SQL, connect)

Осталось прописать route(‘/main’).

app.route('/main')
def main():
    global conn
    selected = select_profile(conn, 1)
    return render_template('main.html', selected=selected)

Теперь после успешной авторизации попадаю на страницу профиля.

Создание страницы «Создание задачи»

По ходу создания task manager у меня получилось подключиться БК и подтянуть из нее данные о пользователе. Применю этот опыт для получения данных о сотрудниках, текущих спринтах и типах задач. Как итог получу шаблон:

Первым делом потребуется создать три новых функции для получения данных из таблиц.

Код файла routes.py

# Получение списка сотрудников
def select_users(connect, created_user):
    SQL = f'''select *
        from tm_schema.task_manager_user
        '''.format(created_user)
    return pd.read_sql_query(SQL, connect)

# Получение списка спринтов
def select_checks(connect, created_user):
    SQL = f'''select *
        from tm_schema.task_manager_check
        '''.format(created_user)
    return pd.read_sql_query(SQL, connect)

# Получение типов задач
def select_task_types(connect, created_user):
    global user_login
    SQL = f'''select *
        from tm_schema.task_manager_dic_task_type
        '''.format(created_user)
    return pd.read_sql_query(SQL, connect)

Следующим шагом будет создание формы с интересующими полями.

Код файла forms.py

class Create_task(FlaskForm):
    task_name = StringField('Название задачи:', validators=[DataRequired()])
    task_created_date = DateTimeField('Дата создания:', format='%d-%m-%Y %H:%M')
    task_in_check = StringField("Спринт:")
    task_created_user = StringField('Пользователь, создавший задачу:')
    task_update_date = DateTimeField('Дата обновления:', format='%d-%m-%Y %H:%M')
    task_update_user = StringField('Пользователь, обновивший задачу:')
    task_description = TextAreaField('Описание задачи:')
    task_control_date = DateTimeField('Контрольная дата:', format='%d-%m-%Y %H:%M')
    task_assigned_date = DateTimeField('Дата назначения:', format='%d-%m-%Y %H:%M')
    to_user = StringField('Кому:') 
    task_priority = SelectField('Приоритет:', choices=[('Низкий', 'Низкий'), ('Средний', 'Средний'), ('Высокий', 'Высокий')], validate_choice=False, validators=[DataRequired()])
    task_type = StringField('Тип задачи:')
    task_status = SelectField('Статус:', choices=[('1', 'Новая'), ('2', 'В работе'), ('3', 'Переназначена'), ('4', 'Закрыта')], default
  • DateTimeField поле выбора даты и времени, в HTML равно тегу <input type=”datetime-local”>;

  • TextAreaField область ввода нескольких строк текста, в HTML равно тегу <textarea></textarea>;

  • SelectField – выпадающий список, в HTML равно тегу <select ></select>.

Функции и форма созданы, теперь пора вернуться к файлу routes.py, чтобы прописать обработку страницы создания задачи.

Код файла routes.py

app.route('/create_task', methods=['GET', 'POST'])
def create_task():
    conn = get_db_connection(user_login, user_password)
    form = Create_task()
    select_user = select_users(conn, 1)
    select_check = select_checks(conn, 1)
    task_type = select_task_types(conn, 1)
    selected = select_profile(conn, 1)
    conn.close()
    if form.validate_on_submit(): . . . .
    return render_template('create_task.html', form=form, select_user=select_user,
                           select_check=select_check, task_type=task_type)

Одним из важных шагов, на котором стоит остановиться подробнее, будет верстка самой страницы.

Код файла create_task.html

{% extends "base.html" %}

{% block title %}Создание задачи{% endblock %}

{% block content_h1 %}
<h1 style="text-align:center">Создание задачи</h1>
{% endblock %}

{% block content %}
<form action="" method="POST"
      style="text-align:center">
    {{ form.hidden_tag() }}
    <!-- Выбор пользователя, кому будет отправлена задача   -->
    <p>
        {{ form.to_user.label }}<br>

        <input name="pers" type="text" list="person">
        <datalist id="person">
            {% for i, user in select_user.iterrows() %}
                <option value="{{ user['user_id']}}">{{ user['login'] }}</option>
            {% endfor %}
        </datalist>
        <br>
        {% for error in form.to_user.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>
    <p>
        {{ form.task_in_check.label }}
        <br>
        <input name="check" type="text" list="check">
        <datalist id="check">
            {% for i, check in select_check.iterrows() %}
                <option value="{{ check['km'] }}">{{ check['name'] }}</option>
            {% endfor %}
        </datalist>
        <br>
        {% for error in form.task_in_check.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>
    <p>
        {{ form.task_name.label }}<br>
        {{ form.task_name(size=35) }}
        <br>
        {% for error in form.task_name.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>
    <p>
        {{ form.task_description.label }}<br>
        {{ form.task_description }}
    </p>
    <p>
        {{ form.task_control_date.label }}
        <br>
        <input name="control_date" type="datetime-local">
        <br>
        {% for error in form.task_control_date.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>
    <p>
        {{ form.task_type.label }}<br>
        <input name="type_task" type="text" list="type_task">
        <datalist id="type_task">
            {% for i, type in task_type.iterrows() %}
                <option value="{{ type['name'] }}"></option>
            {% endfor %}
        </datalist>
        <br>
        {% for error in form.task_type.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>
    <p>
        {{ form.task_priority.label }}
        {{ form.task_priority(length=35) }}
    </p>
    {{ form.submit() }}
</form>
{% endblock %}

Разберу генерацию выпадающего списка

Код файла create_task.html

<p>
        {{ form.to_user.label }}<br>

        <input name="pers" type="text" list="person">
        <datalist id="person">
            {% for i, user in select_user.iterrows() %}
                <option value="{{ user['user_id']}}">{{ user['login'] }}</option>
            {% endfor %}
        </datalist>
        <br>
        {% for error in form.to_user.errors %}
            <span style="color: red;">{{ error }}</span>
        {% endfor %}
    </p>

Для того, чтобы динамически сгенерировать список построчно переберу полученный Data Frame c данными о сотрудниках и выберу нужную информацию.

Остальные списки (Спринт и тип задачи) делаются аналогичным образом.

Теперь нужно прописать получение данных с формы и их обработку в файле routes.py.

Код файла routes.py

if form.validate_on_submit():
    # Создаем переменную где будем считать кол-во ошибок
    err_counter = 0
    # Получение значений переменных
    print('title:\t' + form.task_name.data)
    form.task_created_date.data = datetime.datetime.now()
    print(f'created_date:\t', form.task_created_date.data)

    # Конструкция try-except используем чтобы проверить все поля, а не завершать обработку при первой неудаче. 
    try:
	# Собираем полученные данные с формы и сравниваем их с теми, что есть
        check_temp = select_check[select_check['km'] == request.form["check"]]
	# В случае если результат сравнения не пустой, то сохраняем данные
        form.task_in_check.data = check_temp.iloc[0]['check_id']
    except:
        err_counter = err_counter + 1
        form.task_in_check.errors = ['Поле не может быть пустым!']
    print('check_id:\t' + str(form.task_in_check.data))
    # Сохраняем данные из DataFrame при помощи iloc (Срез по индексам и столбцам) 
    form.task_created_user.data = selected.iloc[0]['user_id']
    print('created_user:\t' + str(form.task_created_user.data))
    # Сохраняем текущее время 
    form.task_update_date.data = datetime.datetime.now()
    print('update_date:\t', form.task_update_date.data)
    # Сохраняем данные из DataFrame при помощи iloc (Срез по индексам и столбцам)
    form.task_update_user.data = selected.iloc[0]['user_id']
    print('update_user:\t' + str(form.task_update_user.data))
    print('description:\t' + form.task_description.data)
    # Сохраняем данные с формы 
    form.task_control_date.data = request.form['control_date']
    # Если переменная пустая, то сообщаем об ошибке
    if form.task_control_date.data == '':
        err_counter = err_counter + 1
        form.task_control_date.errors = ['Поле не может быть пустым!']
    print('control_date:\t' + form.task_control_date.data)
    # Сохраняем текущее время
    form.task_assigned_date.data = datetime.datetime.now()
    print('assigned_date:\t', form.task_assigned_date.data)
    # Сохраняем данные с формы
    form.to_user.data = request.form['pers']
    # Если переменная пустая, то сообщаем об ошибке
    if form.to_user.data == '':
        err_counter = err_counter + 1
        form.to_user.errors = ['Поле не может быть пустым!']
    print('assigned_user\t' + str(form.to_user.data))
    print('priority:\t' + form.task_priority.data)
    try:
        # Собираем полученные данные с формы и сравниваем их с теми, что есть
        task_type_temp = task_type[task_type['name'] == str(request.form['type_task'])]
        # В случае если результат сравнения не пустой, то сохраняем данные
        form.task_type.data = task_type_temp.iloc[0]['task_type_id']
    except:
        err_counter = err_counter + 1
        form.task_type.errors = ['Поле не может быть пустым!']
    print('type:\t', str(form.task_type.data))
    print('status:\t' + form.task_status.data)

    print('Error ---------------------------------', err_counter)
    # Если не было ошибок, то выполняем запрос на внесение данных в таблицу
    if err_counter == 0:
        conn = get_db_connection(user_login, user_password)
        tip = insert_task(conn, 1, form)
        print(tip)
        conn.close()

        return redirect('/select_task_from_me')

Здесь идет присваивание переменным данных из формы, а также поля проверяются на пустоту и корректность данных. В случае, если не было обнаружено ошибок, то выполняется запрос на добавление строки в таблицу.

Код файла routes.py

def insert_task(connect, created_user, form):
    # task_id ,
    try:
        SQL = f'''insert into tm_schema.task_manager_task
            (title, created_date, check_id, created_user, update_date,
             update_user, description, control_date, assigned_date,
             assigned_user, priority, type_id, status_id)
            values (
            '{form.task_name.data}', '{form.task_created_date.data}', '{form.task_in_check.data}',
            '{form.task_created_user.data}', '{form.task_update_date.data}', '{form.task_update_user.data}',
            '{form.task_description.data}', '{form.task_control_date.data}', '{form.task_assigned_date.data}',
            '{form.to_user.data}', '{form.task_priority.data}', '{form.task_type.data}', '{form.task_status.data}'
            )
        '''.format(created_user)
        print(SQL)
        res = pd.read_sql_query(SQL, connect)
        return res

    except Exception as err:

        return err

Ниже будет приведён пример заполненной формы.

Пример создания задачи

1. Выбор исполнителя.

Выполняется поиск по фамилии.

2. Выбор спринта, в рамках которой назначается задача.

Поиск можно выполнить по названию.

3. Далее нужно ввести название и описание задачи.

4. Следующим шагом будет выставление контрольной даты.

5. После выбора контрольной даты нужно выбрать подходящий тип задачи.

6. Последним шагом будет выбор приоритета задачи.

7. Проверка введенных данных

8. После проверки данных нажимаю кнопку «Создать задачу».

Создание страниц просмотра задач

Последним этапом будет создание страниц для просмотра созданных задач. Как и в прошлый раз сначала нужно определиться какие данные нужны и составить правильный запрос к БД.

def select_task_for_user(connect, created_user):
    global user_login
    SQL = f'''
        select 
        task.task_id, task.title, task.created_date, create_user.login as created_user, create_user.email as create_user_email, 
        select_check."name" as check_name, select_check.km as check_km, 
        task.update_date, update_user.login as update_user, update_user.email as update_user_email,
        task.description, task.control_date, task.assigned_date, task.assigned_user,
        assigned_user.login as assigned_username,
        task.priority, task_type."name" as "type", status."name" as "status" 
        from tm_schema.task_manager_task as task
        join tm_schema.task_manager_user as create_user
        on task.created_user = create_user.user_id
        join tm_schema.task_manager_user as update_user
        on task.update_user = update_user.user_id
        join tm_schema.task_manager_check as select_check 
        on task.check_id = select_check.check_id 
        join tm_schema.task_manager_dic_status as status
        on task.status_id = status.status_id 
        join tm_schema.task_manager_dic_task_type as task_type
        on task.type_id = task_type.task_type_id 
        join tm_schema.task_manager_user as assigned_user
        on task.assigned_user = assigned_user.user_id
        where assigned_user={user_login}
    '''.format(created_user)

    return pd.read_sql_query(SQL, connect)

Запрос получился достаточно большой, поэтому стоит разобрать его подробнее.

1. Нужно получать информацию о пользователе, который создал (create_user), обновил (update_user) и является исполнителем задачи (assigned_user).

2. Нужна полная информация о спринте (select_check).

3. А также понадобится узнать статус (status) и тип (task_type) задачи

Следующим шагом будет написание обработки страницы с задачами:

Код файла routes.py

@app.route('/select_task_for_me', methods=['GET', 'POST'])
def select_task_for_me():
    conn = get_db_connection(user_login, user_password)
    my_task = select_task_for_user(conn, 1)
    conn.close()
    if request.method == 'POST':
	...
    return render_template('select_task_for_me.html', my_task=my_task)

Теперь преступлю к верстке самой страницы.

Код файла select_task_for_me.html

{% extends "base.html" %}

{% block title %}Просмотр задач{% endblock %}

{% block content_h1 %}
<h1 style="text-align:center">Просмотр задач</h1>
{% endblock %}

{% block content %}
<div class="container">
    <div class="row">
        {% for i, task in my_task.iterrows() %}
            <div class="col-lg-4 col-sm-12 mb-3">
                <div class="card-tovar">
                    <div class="tovar-details">
                        <form action="" method="post">
                        <table>
                            <tr>
                                <td style="width: 25%">
                                    <input type="hidden" name="id_task" value="{{task['task_id']}}">
                                    <h4>{{task['task_id']}}</h4>
                                </td>
                                <td>
                                    <h4>{{task['title']}}</h4>
                                </td>
                            </tr>
                        </table>
                        <hr>
                        <p>
                           Описание: {{ task['description'] }}
                        </p>
                        <p>
                            Куратор: {{ task['created_user'] }}
                        </p>
                        <p>
                            Статус: {{ task['status'] }}
                        </p>
                        <hr>
                        <p>
                            Срок выполнения: {{ task['control_date'] }}
                        </p>
                        <p>
                            Исполнитель: {{ task['assigned_username'] }}
                        </p>
                        <input type="submit" value="Открыть задачу"
                                   style="width: 100%">
                        </form>
                    </div>
                </div>
            </div>
        {% endfor %}
    </div>
</div>

{% endblock %}

Карточка с заданием будет выглядеть так:

А страница с задачами будет выглядеть так:

Планируемые доработки

  1. Полноценный просмотр задачи (в данный момент в стадии шаблона).

Кнопки «Принять задачу» и «Завершить задачу» будут менять статус задачи на «В работе» и «Закрыта» соответственно.

  1. Кнопка «Переназначить задачу» будет открывать новую страницу с переназначением (в данный момент в стадии шаблона). При переназначении можно будет указать нового исполнителя и добавить комментарии.

  1. Сделать отдельную страницу, где пользователь мог бы просматривать задачи, которые отправил он (страница идентична «Просмотр задач», но имеет другие условия выборки).

  2. При раскрытии карточки задачи со страницы «Задачи, которые назначил я» будет немного другой интерфейс (в данный момент в стадии шаблона).

  1. Будет возможность редактировать отправленную задачу при помощи кнопки «Редактировать задачу». Данные на страницы будут заранее заполнены (в данный момент в стадии шаблона).

Заключение

Вот так я и сделал MVP своего task manager’а. В скором времени будет запущено ограниченное тестирование, чтобы улучшать получившееся ПО. Далее я планирую сделать более приятный глазу дизайн, реализовать пункты из раздела «Планируемые доработки», а также исправить первые баги, которые найдутся в первый день тестирования.

Как только я выпущу стабильную версию task manager’a, то сразу предоставлю к ней свободный доступ и инструкцию для настройки задачника под свою команду.

A Task Manager app is a program that allows users to manage their tasks and to-do lists efficiently. In Python, a Task Manager app can be created using various libraries and frameworks, such as  Tkinter and more

The app will have a graphical user interface (GUI) with the following features:

  1. Add Task: Users can add a new task to the list by providing a task name, description, and due date.
  2. Edit Task: Users can edit the details of an existing task, including the task name, description, and due date.
  3. Delete Task: Users can delete a task from the list.
  4. Mark Task as Complete: Users can mark a task as complete.
  5. View Tasks: Users can view a list of all tasks, including their details such as name, description, due date, and completion status.

The source code for this Task Manager app can be created using the following steps:

  1. Import the necessary libraries, such as Tkinter and DateTime.
  2. Create a class for the app that inherits from Tkinter’s Frame class.
  3. Define the app’s GUI layout using Tkinter’s widgets, such as labels, textboxes, buttons, and list boxes.
  4. Implement the app’s functionality using Python functions, such as adding, editing, deleting, and marking tasks as complete.
  5. Integrate the functions with the GUI widgets using Tkinter’s event binding mechanism.
  6. Create an instance of the app’s class and start the main loop to run the app.

A task manager app in Python can have several features depending on the requirements of the project. Some of the common features that can be included are:

  1. User Authentication: Users should be able to create an account, log in, and log out of the application. This ensures that only authorized users can access the app.
  2. Task Creation: Users should be able to create new tasks by providing a name, description, due date, priority, and status. This allows users to keep track of their work and prioritize their tasks.
  3. Task Management: Users should be able to view, edit, and delete their tasks. The app should also allow users to mark tasks as completed or pending. This helps users to manage their workload efficiently.
  4. Reminder Notifications: The app should send reminder notifications to users when a task is due. This can be done using email, SMS, or push notifications. This ensures that users do not miss their deadlines.
  5. Search Functionality: Users should be able to search for tasks using keywords, filters, or tags. This makes it easy for users to find the tasks they are looking for.
  6. User Interface: The app should have a simple and intuitive user interface. It should be easy to navigate and use, even for users who are not tech-savvy.
  7. Reporting and Analytics: The app can provide users with reports and analytics about their tasks, such as the number of tasks completed, the time taken to complete tasks, and the percentage of tasks completed on time. This helps users to track their progress and identify areas for improvement.
  8. Integration with other tools: The app can be integrated with other tools such as calendars, project management software, and productivity apps. This can help users to manage their tasks across different platforms.
  9. Collaboration: The app can allow users to collaborate on tasks with other users. This can be done by assigning tasks to other users or by allowing multiple users to work on the same task.
  10. Security: The app should be secure and protect users’ data. This can be done by using encryption, secure authentication mechanisms, and regular backups.

Task Manager App in Python Free Source Code Download & Installation Guide

Here is a general guide on how to download and install a Task Manager App in Python with free source code:

  1. First, you need to download & install the Python IDLE’s, here’s the link “https://www.python.org/downloads/”.
  2. Download the source code on this site.
  3. Locate and Extract the zip file.
  4. Open the extracted folder
  5. Locate the py file.
  6. Then open the file via python IDLE or any IDE that supports python language.
    Run the py file to launch the program.

Download source here

  1. How do I schedule a Python task in Windows?
  2. Can we schedule Python script?
  3. How do I make a Python script run automatically daily?
  4. What is Python Task Manager?
  5. How do I create a scheduler in Windows 10?
  6. How do I run a Python function every 5 minutes?
  7. Is python3 exe safe?
  8. What is python exe for?
  9. Do you need Python to run a Python exe?
  10. Which is better py2exe or PyInstaller?
  11. Does PyInstaller exe require Python?

How do I schedule a Python task in Windows?

Step-4: Schedule the Python Script using Windows Scheduler

Next, double-click on the Task Scheduler, and then choose the option to ‘Create Basic Task…’ Type a name for your task (you can also type a description if needed), and then press Next. The action will then recur everyday at 6am, staring from 2019-04-01.

Can we schedule Python script?

One good approach is to schedule these scripts as per your need; daily at 5 PM or weekly once on Sunday 12 AM etc. There are a number tools available at your disposal such as — schedule, apscheduler, python-crontab, apache-airflow, etc. that you can use to schedule your Python jobs .

How do I make a Python script run automatically daily?

Method 2: Using Windows Task Scheduler.

‘ in the Actions Tab. And give a suitable Name and Description of your task that you want to Automate and click on Next. Step 3: In the next step, you have to select at what time intervals your script should be executed. Select ‘Daily’ and click Next.

What is Python Task Manager?

task-manager 6.4. 0

pip install task-manager. Released: Aug 9, 2021. The Task Manager is a server that tracks and dispenses tasks for clients to perform.

How do I create a scheduler in Windows 10?

Open Start, Search for «Task Scheduler» and press enter to open «Task Scheduler». Right-click on the «Task Scheduler Library» and click on the «New Folder» option. Enter the name of the New folder and click on the «OK» button. Navigate the following: Task Scheduler Library > New Folder, then click on «Create Task».

How do I run a Python function every 5 minutes?

With the help of the Schedule module, we can make a python script that will be executed in every given particular time interval. with this function schedule. every(5). minutes.do(func) function will call every 5 minutes.

Is python3 exe safe?

python.exe is a legitimate file and its process known as python.exe. It’s a product of IBM Computers. It is typically located in C:\Program Files\Common Files. Malware programmers create files with malicious codes and name them after python.exe in an attempt to spread virus on the internet.

What is python exe for?

The genuine python.exe file is a software component of Python by Python Software Foundation. Python is a high-level programming language which supports object-oriented, imperative and functional programming or procedural programming styles. Python.exe launches the Python application.

Do you need Python to run a Python exe?

The only realistic way to run a script on Windows without installing Python, is to use py2exe to package it into an executable. Py2exe in turn examines your script, and embeds the proper modules and a python interpreter to run it.

Which is better py2exe or PyInstaller?

In PyInstaller it is easy to create one exe, By default both create a bunch of exes & dlls. In py2exe its easier to embed manifest file in exe, useful for run as administrator mode in windows vista and beyond. Pyinstaller is modular and has a feature of hooks to include files in the build that you like.

Does PyInstaller exe require Python?

They do not need to have Python installed at all. The output of PyInstaller is specific to the active operating system and the active version of Python. This means that to prepare a distribution for: a different OS.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Куда устанавливается whatsapp в windows 10
  • При перезагрузке не загружается windows
  • Настройка веб сервера iis для 1с на windows server 2019
  • Как сделать загрузочную флешку windows 10 на linux ubuntu
  • Не устанавливается exe файл на windows 10