From ac1b7f8a2d77880c061081a94bda9bb053933a27 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 20 Jan 2017 17:28:24 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B5=D1=85=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=BD=D0=B0=20python3!=20=D0=A3=D1=80=D0=B0!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + abonapp/admin.py | 2 +- abonapp/forms.py | 12 +-- abonapp/migrations/0001_initial.py | 3 +- abonapp/migrations/0002_auto_20161206_2135.py | 1 - abonapp/migrations/0003_abongroup_profiles.py | 1 - abonapp/migrations/0004_auto_20161220_0102.py | 1 - abonapp/migrations/0005_auto_20161226_0054.py | 7 +- abonapp/models.py | 36 +++---- abonapp/tests.py | 10 +- abonapp/urls.py | 2 +- abonapp/urls_abon.py | 2 +- abonapp/views.py | 100 +++++++++--------- accounts_app/admin.py | 2 +- accounts_app/forms.py | 2 +- accounts_app/migrations/0001_initial.py | 5 +- .../migrations/0002_userprofile_email.py | 1 - .../migrations/0003_auto_20161206_2135.py | 6 +- accounts_app/models.py | 4 +- accounts_app/urls.py | 2 +- accounts_app/views.py | 16 +-- agent/__init__.py | 6 +- agent/core.py | 12 +-- agent/mod_mikrotik.py | 90 +++++++--------- agent/netflow/to_mysql.py | 4 +- agent/structs.py | 10 +- chatbot/admin.py | 2 +- chatbot/migrations/0001_initial.py | 1 - chatbot/models.py | 8 +- chatbot/telebot.py | 35 +++--- clientsideapp/models.py | 2 +- clientsideapp/urls.py | 2 +- clientsideapp/views.py | 12 +-- devapp/admin.py | 2 +- devapp/apps.py | 2 +- devapp/base_intr.py | 11 +- devapp/dev_types.py | 10 +- devapp/forms.py | 2 +- devapp/migrations/0001_initial.py | 9 +- devapp/migrations/0002_auto_20160909_1018.py | 1 - devapp/models.py | 12 +-- devapp/tests.py | 12 +-- devapp/urls.py | 2 +- devapp/views.py | 16 +-- djing/urls.py | 4 +- djing/utils/load_from_nodeny.py | 2 +- djing/utils/push_snmp_passw.py | 4 +- djing/utils/save_dot_from_nodeny.py | 2 +- djing/utils/save_from_nodeny.py | 4 +- gmap/apps.py | 2 +- gmap/migrations/0001_initial.py | 23 ++-- gmap/models.py | 70 ++++++------ gmap/utils.py | 26 ++--- gmap/views.py | 4 +- ip_pool/admin.py | 2 +- ip_pool/apps.py | 2 +- ip_pool/forms.py | 8 +- ip_pool/migrations/0001_initial.py | 3 +- ip_pool/models.py | 6 +- ip_pool/urls.py | 2 +- ip_pool/views.py | 8 +- manage.py | 2 +- mydefs.py | 33 +++--- photo_app/admin.py | 2 +- photo_app/migrations/0001_initial.py | 5 +- photo_app/models.py | 6 +- privatemessage/admin.py | 2 +- privatemessage/context_processors.py | 2 +- privatemessage/migrations/0001_initial.py | 1 - privatemessage/models.py | 4 +- privatemessage/tests.py | 2 +- privatemessage/urls.py | 2 +- privatemessage/views.py | 10 +- requirements.txt | 1 + searchapp/apps.py | 2 +- searchapp/models.py | 2 +- searchapp/urls.py | 2 +- statistics/admin.py | 2 +- statistics/migrations/0001_initial.py | 5 +- statistics/models.py | 2 +- statistics/urls.py | 2 +- tariff_app/admin.py | 2 +- tariff_app/base_intr.py | 6 +- tariff_app/custom_tariffs.py | 8 +- tariff_app/forms.py | 2 +- tariff_app/migrations/0001_initial.py | 10 +- tariff_app/migrations/0002_tariff_descr.py | 1 - tariff_app/models.py | 10 +- tariff_app/urls.py | 2 +- tariff_app/views.py | 6 +- taskapp/admin.py | 2 +- taskapp/forms.py | 4 +- taskapp/handle.py | 52 +++++---- taskapp/migrations/0001_initial.py | 3 +- taskapp/migrations/0002_auto_20161006_0027.py | 3 +- taskapp/migrations/0003_auto_20161130_1815.py | 1 - taskapp/migrations/0004_auto_20161202_1230.py | 3 +- taskapp/migrations/0005_auto_20161206_0013.py | 1 - taskapp/migrations/0006_auto_20161206_2135.py | 5 +- taskapp/migrations/0007_auto_20161206_2303.py | 1 - taskapp/migrations/0008_auto_20161213_1932.py | 5 +- taskapp/migrations/0009_auto_20161216_2214.py | 1 - taskapp/migrations/0010_auto.py | 5 +- taskapp/migrations/0011_auto_20170116_0126.py | 1 - taskapp/models.py | 86 ++++++--------- taskapp/urls.py | 2 +- taskapp/views.py | 20 ++-- 107 files changed, 462 insertions(+), 520 deletions(-) diff --git a/.gitignore b/.gitignore index 2f8363c..d67e48d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ djing/settings.py gmap/fixtures *.sqlite3 *.json +*.bak diff --git a/abonapp/admin.py b/abonapp/admin.py index 3efc634..68169eb 100644 --- a/abonapp/admin.py +++ b/abonapp/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.AbonGroup) diff --git a/abonapp/forms.py b/abonapp/forms.py index 6f5107f..730a1a2 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -2,24 +2,24 @@ from django import forms from django.core.validators import RegexValidator -import models +from . import models from mydefs import ip_addr_regex class AbonForm(forms.Form): username = forms.CharField(max_length=127, required=False, widget=forms.TextInput(attrs={ - 'placeholder': u'Логин', + 'placeholder': 'Логин', 'class': "form-control", 'id': "login" })) fio = forms.CharField(max_length=256, widget=forms.TextInput(attrs={ - 'placeholder': u'ФИО', + 'placeholder': 'ФИО', 'class': "form-control", 'id': "fio" }), required=False) - ip_address = forms.GenericIPAddressField(protocol='IPv4', required=False, widget=forms.TextInput(attrs={ + ip_address = forms.GenericIPAddressField(protocol='ipv4', required=False, widget=forms.TextInput(attrs={ 'pattern': ip_addr_regex, - 'placeholder': u'127.0.0.1', + 'placeholder': '127.0.0.1', 'class': "form-control", 'id': "ip" })) @@ -28,7 +28,7 @@ class AbonForm(forms.Form): max_length=16, validators=[RegexValidator(r'^\+[7,8,9,3]\d{10,11}$')], widget=forms.TextInput(attrs={ - 'placeholder': u'+[7,8,9,3] и 10,11 цифр', + 'placeholder': '+[7,8,9,3] и 10,11 цифр', 'pattern': r'^\+[7,8,9,3]\d{10,11}$', 'required': '', 'class': 'form-control', diff --git a/abonapp/migrations/0001_initial.py b/abonapp/migrations/0001_initial.py index b7a94bc..1e95fb1 100644 --- a/abonapp/migrations/0001_initial.py +++ b/abonapp/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.conf import settings import django.core.validators @@ -111,6 +110,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='abontariff', - unique_together=set([('abon', 'tariff', 'tariff_priority')]), + unique_together={('abon', 'tariff', 'tariff_priority')}, ), ] diff --git a/abonapp/migrations/0002_auto_20161206_2135.py b/abonapp/migrations/0002_auto_20161206_2135.py index ef7073d..a865928 100644 --- a/abonapp/migrations/0002_auto_20161206_2135.py +++ b/abonapp/migrations/0002_auto_20161206_2135.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-06 18:35 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/abonapp/migrations/0003_abongroup_profiles.py b/abonapp/migrations/0003_abongroup_profiles.py index 5d57a50..8a4f986 100644 --- a/abonapp/migrations/0003_abongroup_profiles.py +++ b/abonapp/migrations/0003_abongroup_profiles.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-16 19:14 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models diff --git a/abonapp/migrations/0004_auto_20161220_0102.py b/abonapp/migrations/0004_auto_20161220_0102.py index 0953149..4c95597 100644 --- a/abonapp/migrations/0004_auto_20161220_0102.py +++ b/abonapp/migrations/0004_auto_20161220_0102.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-19 22:02 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models diff --git a/abonapp/migrations/0005_auto_20161226_0054.py b/abonapp/migrations/0005_auto_20161226_0054.py index 4d7bd0f..fe3aa96 100644 --- a/abonapp/migrations/0005_auto_20161226_0054.py +++ b/abonapp/migrations/0005_auto_20161226_0054.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-25 21:54 -from __future__ import unicode_literals from django.db import migrations @@ -14,14 +13,14 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='abon', - options={'permissions': (('can_buy_tariff', '\u041f\u043e\u043a\u0443\u043f\u043a\u0430 \u0442\u0430\u0440\u0438\u0444\u0430 \u0430\u0431\u043e\u043d\u0435\u043d\u0442\u0443'),)}, + options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'),)}, ), migrations.AlterModelOptions( name='abongroup', - options={'permissions': (('can_add_ballance', '\u041f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0447\u0451\u0442\u0430'),)}, + options={'permissions': (('can_add_ballance', 'Пополнение счёта'),)}, ), migrations.AlterModelOptions( name='abontariff', - options={'ordering': ('tariff_priority',), 'permissions': (('can_complete_service', '\u0414\u043e\u0441\u0440\u043e\u0447\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0443\u0441\u043b\u0443\u0433\u0438 \u0430\u0431\u043e\u043d\u0435\u043d\u0442\u0430'), ('can_activate_service', '\u0410\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u0443\u0441\u043b\u0443\u0433\u0438 \u0430\u0431\u043e\u043d\u0435\u043d\u0442\u0430'))}, + options={'ordering': ('tariff_priority',), 'permissions': (('can_complete_service', 'Досрочное завершение услуги абонента'), ('can_activate_service', 'Активация услуги абонента'))}, ), ] diff --git a/abonapp/models.py b/abonapp/models.py index 623c6ae..2773637 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -14,12 +14,10 @@ from accounts_app.models import UserProfile class LogicError(Exception): - def __init__(self, value, err_id=None): + def __init__(self, value): self.message = value - if err_id: - self.err_id = err_id - def __unicode__(self): + def __str__(self): return repr(self.message) def __str__(self): @@ -36,7 +34,7 @@ class AbonGroup(models.Model): ('can_add_ballance', 'Пополнение счёта'), ) - def __unicode__(self): + def __str__(self): return self.title @@ -50,7 +48,7 @@ class AbonLog(models.Model): class Meta: db_table = 'abonent_log' - def __unicode__(self): + def __str__(self): return self.comment @@ -124,7 +122,7 @@ class AbonTariff(models.Model): amnt = self.calc_amount_service() # если не хватает денег if self.abon.ballance < amnt: - raise LogicError(u'Не хватает денег на счету') + raise LogicError('Не хватает денег на счету') # дата активации услуги self.time_start = timezone.now() # снимаем деньги за услугу @@ -135,7 +133,7 @@ class AbonTariff(models.Model): def is_started(self): return True if self.time_start is not None else False - def __unicode__(self): + def __str__(self): return "%d: '%s' - '%s'" % ( self.tariff_priority, self.tariff.title, @@ -147,8 +145,8 @@ class AbonTariff(models.Model): db_table = 'abonent_tariff' unique_together = (('abon', 'tariff', 'tariff_priority'),) permissions = ( - ('can_complete_service', u'Досрочное завершение услуги абонента'), - ('can_activate_service', u'Активация услуги абонента') + ('can_complete_service', 'Досрочное завершение услуги абонента'), + ('can_activate_service', 'Активация услуги абонента') ) @@ -188,18 +186,18 @@ class Abon(UserProfile): self.group = cd['group'] self.address = cd['address'] except Http404: - raise LogicError(u'Введённый IP адрес не добавлен в ip pool') + raise LogicError('Введённый IP адрес не добавлен в ip pool') except MultipleObjectsReturned: - raise LogicError(u'Введённый IP адрес не определён') + raise LogicError('Введённый IP адрес не определён') class Meta: db_table = 'abonent' permissions = ( - ('can_buy_tariff', u'Покупка тарифа абоненту'), + ('can_buy_tariff', 'Покупка тарифа абоненту'), ) # Платим за что-то - def make_pay(self, curuser, how_match_to_pay=0.0, u_comment=u'Снятие со счёта средств'): + def make_pay(self, curuser, how_match_to_pay=0.0, u_comment='Снятие со счёта средств'): AbonLog.objects.create( abon=self, amount=-how_match_to_pay, @@ -214,7 +212,7 @@ class Abon(UserProfile): abon=self, amount=amount, author=current_user, - comment=u'Пополнение счёта через админку' + comment='Пополнение счёта через админку' ) self.ballance += amount @@ -244,7 +242,7 @@ class Abon(UserProfile): AbonLog.objects.create( abon=self, amount=-tariff.amount, author=author, - comment=u'Покупка тарифного плана через админку, тариф "%s"' % tariff.title + comment='Покупка тарифного плана через админку, тариф "%s"' % tariff.title ) # Пробует подключить новую услугу если пришло время @@ -265,7 +263,7 @@ class Abon(UserProfile): # И от заказа тарифа до начала этого месяца if (nw - at.time_start) > (nw - to_start_month): # Заказ из прошлого месяца, срок действия закончен - print u'Заказ из прошлого месяца, срок действия закончен' + print('Заказ из прошлого месяца, срок действия закончен') # выберем следующую по приоритету # next_tarifs = AbonTariff.objects.filter(tariff_priority__gt = self.tariff_priority, abon=self.abon) @@ -284,7 +282,7 @@ class Abon(UserProfile): abon=self, amount=0, author=author, - comment=u'Завершение услуги по истечению срока действия' + comment='Завершение услуги по истечению срока действия' ) # есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs..manage_access() @@ -307,7 +305,7 @@ class InvoiceForPayment(models.Model): date_pay = models.DateTimeField(blank=True, null=True) author = models.ForeignKey(UserProfile, related_name='+') - def __unicode__(self): + def __str__(self): return "%s -> %d $" % (self.abon.username, self.amount) def set_ok(self): diff --git a/abonapp/tests.py b/abonapp/tests.py index ce731d1..040f05f 100644 --- a/abonapp/tests.py +++ b/abonapp/tests.py @@ -2,7 +2,7 @@ from django.shortcuts import get_object_or_404 from django.test import TestCase -from models import Abon, AbonTariff +from .models import Abon, AbonTariff from tariff_app.models import Tariff @@ -10,17 +10,17 @@ class AbonTariffTestCase(TestCase): def setUp(self): abon1 = Abon.objects.create( telephone='+79784653751', - fio=u'ФИО абона', + fio='ФИО абона', username='аго мучич' ) tarif1 = Tariff.objects.create( - title=u'Тариф 1', + title='Тариф 1', speedIn=120.3, speedOut=53, amount=38 ) tarif2 = Tariff.objects.create( - title=u'Тариф 2', + title='Тариф 2', speedIn=130.3, speedOut=23, amount=82 @@ -38,7 +38,7 @@ class AbonTariffTestCase(TestCase): def test_activate_next(self): # возьмём абонента для опытов - abn = get_object_or_404(Abon, username=u'аго мучич') + abn = get_object_or_404(Abon, username='аго мучич') # берём купленные услуги ats = AbonTariff.objects.filter(abon=abn) diff --git a/abonapp/urls.py b/abonapp/urls.py index 510bd1e..25699da 100644 --- a/abonapp/urls.py +++ b/abonapp/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url, include -import views +from . import views urlpatterns = [ diff --git a/abonapp/urls_abon.py b/abonapp/urls_abon.py index 0a35b57..a01dc7e 100644 --- a/abonapp/urls_abon.py +++ b/abonapp/urls_abon.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/abonapp/views.py b/abonapp/views.py index 2273d5a..534e6f4 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -14,8 +14,8 @@ from django.contrib import messages from ip_pool.models import IpPoolItem from tariff_app.models import Tariff from agent import NasFailedResult, AbonStruct, Transmitter, TariffStruct, NasNetworkError -import forms -import models +from . import forms +from . import models import mydefs @@ -48,14 +48,14 @@ def addgroup(request): frm = forms.AbonGroupForm(request.POST) if frm.is_valid(): frm.save() - messages.success(request, u'Группа успешно создана') + messages.success(request, 'Группа успешно создана') return redirect('abonapp:group_list') else: - messages.error(request, u'Исправьте ошибки') + messages.error(request, 'Исправьте ошибки') except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'abonapp/addGroup.html', { 'form': frm }) @@ -88,9 +88,9 @@ def delgroup(request): get_object_or_404(models.AbonGroup, id=agd).delete() return mydefs.res_success(request, 'abonapp:group_list') except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return mydefs.res_error(request, 'abonapp:group_list') @@ -110,16 +110,16 @@ def addabon(request, gid): prf.save() return redirect('abonapp:people_list', group.id) else: - messages.error(request, u'Некоторые поля заполнены не правильно, проверте ещё раз') + messages.error(request, 'Некоторые поля заполнены не правильно, проверте ещё раз') except IntegrityError as e: - messages.error(request, e.message) + messages.error(request, e) except models.LogicError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) if not frm: frm = forms.AbonForm(initial={ @@ -153,9 +153,9 @@ def delentity(request): get_object_or_404(models.AbonGroup, id=uid).delete() return mydefs.res_success(request, 'abonapp:group_list') except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) return redirect('abonapp:group_list') @@ -170,14 +170,14 @@ def abonamount(request, gid, uid): amnt = mydefs.safe_float(request.POST.get('amount')) abon.add_ballance(request.user, amnt) abon.save(update_fields=['ballance']) - messages.success(request, u'Счёт успешно пополнен на %d' % amnt) + messages.success(request, 'Счёт успешно пополнен на %d' % amnt) return redirect('abonapp:abon_home', gid=gid, uid=uid) else: - messages.error(request, u'Не могу разобрать id абонента') + messages.error(request, 'Не могу разобрать id абонента') except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'abonapp/abonamount.html', { 'abon': abon, 'abon_group': get_object_or_404(models.AbonGroup, id=gid) @@ -236,7 +236,7 @@ def abonhome(request, gid, uid): init_frm_dat = { 'username': abon.username, 'fio': abon.fio, - 'ip_address': abon.ip_address or u'Не назначен', + 'ip_address': abon.ip_address or 'Не назначен', 'telephone': abon.telephone, 'group': abon.group, 'address': abon.address, @@ -259,21 +259,21 @@ def abonhome(request, gid, uid): # return redirect('abonapp:abon_home', gid, uid) else: - messages.warning(request, u'Не правильные значения, проверте поля и попробуйте ещё') + messages.warning(request, 'Не правильные значения, проверте поля и попробуйте ещё') else: frm = forms.AbonForm(initial=init_frm_dat) except IntegrityError as e: - messages.error(request, u'Проверте введённые вами значения, скорее всего такой ip уже у кого-то есть. А вообще: %s' % e.message) + messages.error(request, 'Проверте введённые вами значения, скорее всего такой ip уже у кого-то есть. А вообще: %s' % e) frm = forms.AbonForm(initial=init_frm_dat) except Http404: - messages.error(request, u'Ip адрес не найден в списке IP адресов') + messages.error(request, 'Ip адрес не найден в списке IP адресов') frm = forms.AbonForm(initial=init_frm_dat) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'abonapp/editAbon.html', { 'form': frm or forms.AbonForm(initial=init_frm_dat), @@ -313,7 +313,7 @@ def add_invoice(request, gid, uid): newinv.amount = curr_amount newinv.comment = comment - if request.POST.get('status') == u'on': + if request.POST.get('status') == 'on': newinv.status = True newinv.author = request.user @@ -321,9 +321,9 @@ def add_invoice(request, gid, uid): return redirect('abonapp:abon_home', gid=gid, uid=uid) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'abonapp/addInvoice.html', { 'abon': abon, 'invcount': models.InvoiceForPayment.objects.filter(abon=abon).count(), @@ -346,15 +346,15 @@ def buy_tariff(request, gid, uid): abon.save() return redirect('abonapp:abon_services', gid=gid, uid=abon.id) else: - messages.error(request, u'Что-то не так при покупке услуги, проверьте и попробуйте ещё') + messages.error(request, 'Что-то не так при покупке услуги, проверьте и попробуйте ещё') else: frm = forms.BuyTariff() except models.LogicError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return redirect('abonapp:abon_services', gid=gid, uid=abon.id) return render(request, 'abonapp/buy_tariff.html', { @@ -378,9 +378,9 @@ def chpriority(request, gid, uid): elif act == 'down': current_abon_tariff.priority_down() except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return redirect('abonapp:abon_home', gid=gid, uid=uid) @@ -400,19 +400,19 @@ def complete_service(request, gid, uid, srvid): if finish_confirm == 'yes': # удаляем запись о текущей услуге. abtar.delete() - messages.success(request, u'Услуга успешно завершена') + messages.success(request, 'Услуга успешно завершена') return redirect('abonapp:abon_home', gid, uid) else: - raise models.LogicError(u'Действие не подтверждено') + raise models.LogicError('Действие не подтверждено') time_use = mydefs.RuTimedelta(timezone.now() - abtar.time_start) except models.LogicError as e: - messages.error(request, e.message) + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.warning(request, e.message) + messages.warning(request, e) return redirect('abonapp:abon_home', gid, uid) return render(request, 'abonapp/complete_service.html', { @@ -438,11 +438,11 @@ def activate_service(request, gid, uid, srvid): return redirect('abonapp:abon_home', gid, uid) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.warning(request, e.message) + messages.warning(request, e) except models.LogicError as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'abonapp/activate_service.html', { 'abon': abtar.abon, 'abon_group': abtar.abon.group, @@ -458,9 +458,9 @@ def unsubscribe_service(request, gid, uid, srvid): try: get_object_or_404(models.AbonTariff, id=int(srvid)).delete() except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.warning(request, e.message) + messages.warning(request, e) return redirect('abonapp:abon_home', gid=gid, uid=uid) @@ -512,27 +512,27 @@ def update_nas(request, group_id): except NasFailedResult: tm.add_user(agent_abon) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.warning(request, e.message) + messages.warning(request, e) return redirect('abonapp:people_list', gid=group_id) # API's def abons(request): - ablist = map(lambda abn: { + ablist = [{ 'id': abn.id, 'tarif_id': abn.active_tariff().id if abn.active_tariff() else 0, 'ip': abn.ip_address.int_ip(), 'is_active': abn.is_active - }, models.Abon.objects.all()) + } for abn in models.Abon.objects.all()] - tarlist = map(lambda trf: { + tarlist = [{ 'id': trf.id, 'speedIn': trf.speedIn, 'speedOut': trf.speedOut - }, Tariff.objects.all()) + } for trf in Tariff.objects.all()] data = { 'subscribers': ablist, diff --git a/accounts_app/admin.py b/accounts_app/admin.py index 473e805..caeb394 100644 --- a/accounts_app/admin.py +++ b/accounts_app/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from models import UserProfile +from .models import UserProfile admin.site.register(UserProfile) diff --git a/accounts_app/forms.py b/accounts_app/forms.py index 6210c0d..fbedf6f 100644 --- a/accounts_app/forms.py +++ b/accounts_app/forms.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from django import forms -from models import UserProfile +from .models import UserProfile class SetupPerms(forms.ModelForm): diff --git a/accounts_app/migrations/0001_initial.py b/accounts_app/migrations/0001_initial.py index 02ceb2c..a51ca18 100644 --- a/accounts_app/migrations/0001_initial.py +++ b/accounts_app/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals import django.core.validators from django.db import migrations, models @@ -31,8 +30,8 @@ class Migration(migrations.Migration): ('is_active', models.BooleanField(default=True)), ('is_admin', models.BooleanField(default=False)), ('telephone', models.CharField(max_length=16, unique=True, validators=[ - django.core.validators.RegexValidator(b'^\\+[7,8,9,3]\\d{10,11}$')], - verbose_name=b'Telephone number')), + django.core.validators.RegexValidator(r'^\\+[7,8,9,3]\\d{10,11}$')], + verbose_name='Telephone number')), ('skype', models.CharField(blank=True, max_length=20)), ('avatar', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='photo_app.Photo')), diff --git a/accounts_app/migrations/0002_userprofile_email.py b/accounts_app/migrations/0002_userprofile_email.py index 6930dfe..d743381 100644 --- a/accounts_app/migrations/0002_userprofile_email.py +++ b/accounts_app/migrations/0002_userprofile_email.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-11-30 15:15 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/accounts_app/migrations/0003_auto_20161206_2135.py b/accounts_app/migrations/0003_auto_20161206_2135.py index cd3c461..7f155dd 100644 --- a/accounts_app/migrations/0003_auto_20161206_2135.py +++ b/accounts_app/migrations/0003_auto_20161206_2135.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-06 18:35 -from __future__ import unicode_literals import django.core.validators from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('accounts_app', '0002_userprofile_email'), ] @@ -20,6 +18,8 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='userprofile', name='telephone', - field=models.CharField(max_length=16, validators=[django.core.validators.RegexValidator(b'^\\+[7,8,9,3]\\d{10,11}$')], verbose_name=b'Telephone number'), + field=models.CharField(max_length=16, + validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], + verbose_name='Telephone number'), ), ] diff --git a/accounts_app/models.py b/accounts_app/models.py index 637d5bd..f16961a 100644 --- a/accounts_app/models.py +++ b/accounts_app/models.py @@ -50,7 +50,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): max_length=16, verbose_name='Telephone number', #unique=True, - validators=[RegexValidator(r'^\+[7,8,9,3]\d{10,11}$')] + validators=[RegexValidator('^\+[7,8,9,3]\d{10,11}$')] ) avatar = models.ForeignKey(Photo, null=True, blank=True) email = models.EmailField() @@ -86,5 +86,5 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): else: return DEFAULT_PICTURE - def __unicode__(self): + def __str__(self): return self.get_full_name() diff --git a/accounts_app/urls.py b/accounts_app/urls.py index ece0703..adeb5ef 100644 --- a/accounts_app/urls.py +++ b/accounts_app/urls.py @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/accounts_app/views.py b/accounts_app/views.py index 98208b4..ec93c4b 100644 --- a/accounts_app/views.py +++ b/accounts_app/views.py @@ -10,7 +10,7 @@ from django.contrib import messages from abonapp.models import AbonGroup from photo_app.models import Photo -from models import UserProfile +from .models import UserProfile import mydefs @@ -39,13 +39,13 @@ def to_signin(request): return render(request, 'accounts/login.html', { 'next': nextl, - 'errmsg': u'Неправильный логин или пароль, попробуйте ещё раз' + 'errmsg': 'Неправильный логин или пароль, попробуйте ещё раз' }) return render(request, 'accounts/login.html', { 'next': nextl }) except NoReverseMatch: - raise Http404(u"Destination page does not exist") + raise Http404("Destination page does not exist") def sign_out(request): @@ -133,7 +133,7 @@ def ch_info(request): newpasswd = request.POST.get('newpasswd') user.set_password(newpasswd) else: - messages.error(request, u'Неправильный пароль') + messages.error(request, 'Неправильный пароль') user.save() request.user = user @@ -158,10 +158,10 @@ def create_profile(request): passwd = request.POST.get('passwd') conpasswd = request.POST.get('conpasswd') if not passwd: - messages.error(request, u'Забыли указать пароль для нового аккаунта') + messages.error(request, 'Забыли указать пароль для нового аккаунта') if not conpasswd: - messages.error(request, u'Забыли повторить пароль для нового аккаунта') + messages.error(request, 'Забыли повторить пароль для нового аккаунта') if passwd == conpasswd: user_qs = UserProfile.objects.filter(username=username)[:1] @@ -170,9 +170,9 @@ def create_profile(request): user.save() return redirect('acc_app:accounts_list') else: - messages.error(request, u'Пользователь с таким именем уже есть') + messages.error(request, 'Пользователь с таким именем уже есть') else: - messages.error(request, u'Пароли не совпадают, попробуйте ещё раз') + messages.error(request, 'Пароли не совпадают, попробуйте ещё раз') return render(request, 'accounts/create_acc.html', { 'newuser': user }) diff --git a/agent/__init__.py b/agent/__init__.py index a95b91d..e46de30 100644 --- a/agent/__init__.py +++ b/agent/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf8 -*- -from mod_mikrotik import MikrotikTransmitter -from core import NasFailedResult, NasNetworkError -from structs import TariffStruct, AbonStruct +from .mod_mikrotik import MikrotikTransmitter +from .core import NasFailedResult, NasNetworkError +from .structs import TariffStruct, AbonStruct # Transmitter мы будем импортировать в других местах diff --git a/agent/core.py b/agent/core.py index 085bf69..95f25f1 100644 --- a/agent/core.py +++ b/agent/core.py @@ -1,18 +1,16 @@ # -*- coding: utf8 -*- from abc import ABCMeta, abstractmethod -from structs import AbonStruct, TariffStruct +from .structs import AbonStruct, TariffStruct # Всплывает если из NAS вернулся не удачный результат class NasFailedResult(Exception): - def __init__(self, message): - super(NasFailedResult, self).__init__(message) + pass # Всплывает когда нет связи с сервером доступа к инету (NAS) class NasNetworkError(Exception): - def __init__(self, message): - super(NasNetworkError, self).__init__(message) + pass # Проверяет входной тип на принадлежность классу. @@ -32,9 +30,7 @@ def check_input_type(class_or_type): # Общается с NAS'ом -class BaseTransmitter(object): - __metaclass__ = ABCMeta - +class BaseTransmitter(metaclass=ABCMeta): @abstractmethod @check_input_type(AbonStruct) def add_user_range(self, user_list): diff --git a/agent/mod_mikrotik.py b/agent/mod_mikrotik.py index c6e9962..90fc4df 100644 --- a/agent/mod_mikrotik.py +++ b/agent/mod_mikrotik.py @@ -2,15 +2,14 @@ import socket import binascii from hashlib import md5 -from core import BaseTransmitter, NasFailedResult, NasNetworkError +from .core import BaseTransmitter, NasFailedResult, NasNetworkError from mydefs import ping -from structs import TariffStruct, IpStruct -import settings +from .structs import TariffStruct, IpStruct +from . import settings class ApiRos: "Routeros api" - def __init__(self, sk): self.sk = sk self.currenttag = 0 @@ -19,11 +18,11 @@ class ApiRos: for repl, attrs in self.talk(["/login"]): chal = binascii.unhexlify(attrs['=ret']) md = md5() - md.update('\x00') - md.update(pwd) + md.update(b'\x00') + md.update(bytes(pwd, 'utf-8')) md.update(chal) self.talk(["/login", "=name=" + username, - "=response=00" + binascii.hexlify(md.digest())]) + "=response=00" + binascii.hexlify(md.digest()).decode('utf-8')]) def talk(self, words): if self.writeSentence(words) == 0: return @@ -35,10 +34,10 @@ class ApiRos: attrs = {} for w in i[1:]: j = w.find('=', 1) - if j == -1: + if (j == -1): attrs[w] = '' else: - attrs[w[:j]] = w[j + 1:] + attrs[w[:j]] = w[j+1:] r.append((reply, attrs)) if reply == '!done': return r @@ -58,84 +57,75 @@ class ApiRos: r.append(w) def writeWord(self, w): - print "<<< " + w - self.writeLen(len(w)) - self.writeStr(w) + print("<<< " + w) + b = bytes(w, "utf-8") + self.writeLen(len(b)) + self.writeBytes(b) def readWord(self): - ret = self.readStr(self.readLen()) - print ">>> " + ret + ret = self.readBytes(self.readLen()).decode('utf-8') + print(">>> " + ret) return ret def writeLen(self, l): if l < 0x80: - self.writeStr(chr(l)) + self.writeBytes(bytes([l])) elif l < 0x4000: l |= 0x8000 - self.writeStr(chr((l >> 8) & 0xFF)) - self.writeStr(chr(l & 0xFF)) + self.writeBytes(bytes([(l >> 8) & 0xff, l & 0xff])) elif l < 0x200000: l |= 0xC00000 - self.writeStr(chr((l >> 16) & 0xFF)) - self.writeStr(chr((l >> 8) & 0xFF)) - self.writeStr(chr(l & 0xFF)) + self.writeBytes(bytes([(l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff])) elif l < 0x10000000: l |= 0xE0000000 - self.writeStr(chr((l >> 24) & 0xFF)) - self.writeStr(chr((l >> 16) & 0xFF)) - self.writeStr(chr((l >> 8) & 0xFF)) - self.writeStr(chr(l & 0xFF)) + self.writeBytes(bytes([(l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff])) else: - self.writeStr(chr(0xF0)) - self.writeStr(chr((l >> 24) & 0xFF)) - self.writeStr(chr((l >> 16) & 0xFF)) - self.writeStr(chr((l >> 8) & 0xFF)) - self.writeStr(chr(l & 0xFF)) + self.writeBytes(bytes([0xf0, (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff])) def readLen(self): - c = ord(self.readStr(1)) + c = self.readBytes(1)[0] if (c & 0x80) == 0x00: pass elif (c & 0xC0) == 0x80: c &= ~0xC0 c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] elif (c & 0xE0) == 0xC0: c &= ~0xE0 c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] elif (c & 0xF0) == 0xE0: c &= ~0xF0 c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] elif (c & 0xF8) == 0xF0: - c = ord(self.readStr(1)) + c = self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] c <<= 8 - c += ord(self.readStr(1)) + c += self.readBytes(1)[0] return c - def writeStr(self, text): - n = 0 - while n < len(text): - r = self.sk.send(text[n:]) - if r == 0: raise RuntimeError, "connection closed by remote end" + def writeBytes(self, str): + n = 0; + while n < len(str): + r = self.sk.send(str[n:]) + if r == 0: raise RuntimeError("connection closed by remote end") n += r - def readStr(self, length): - ret = '' + def readBytes(self, length): + ret = b'' while len(ret) < length: s = self.sk.recv(length - len(ret)) - if s == '': raise RuntimeError, "connection closed by remote end" + if len(s) == 0: raise RuntimeError("connection closed by remote end") ret += s return ret @@ -145,7 +135,7 @@ class MikrotikTransmitter(BaseTransmitter): def __init__(self, login=None, password=None, ip=None, port=None): ip = ip or settings.NAS_IP if not ping(ip): - raise NasNetworkError(u'NAS %s не пингуется' % ip) + raise NasNetworkError('NAS %s не пингуется' % ip) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port or settings.NAS_PORT)) self.ar = ApiRos(s) @@ -165,7 +155,7 @@ class MikrotikTransmitter(BaseTransmitter): return ret[0][1] def add_user_range(self, user_list): - return map(self.add_user, user_list) + return list(map(self.add_user, user_list)) def remove_user_range(self, user_list): names = ['uid%d' % usr.uid for usr in user_list] diff --git a/agent/netflow/to_mysql.py b/agent/netflow/to_mysql.py index a190f38..de1c92d 100755 --- a/agent/netflow/to_mysql.py +++ b/agent/netflow/to_mysql.py @@ -33,7 +33,7 @@ def convert(query): if __name__ == '__main__': f = sys.stdin table_name = "flowstat_%s" % datetime.now().strftime("%d%m%Y") - print("CREATE TABLE IF NOT EXISTS %s (" % table_name) + print(("CREATE TABLE IF NOT EXISTS %s (" % table_name)) print("`id` int(10) AUTO_INCREMENT NOT NULL,") print("`src_ip` INT(10) UNSIGNED NOT NULL,") print("`dst_ip` INT(10) UNSIGNED NOT NULL,") @@ -55,7 +55,7 @@ if __name__ == '__main__': if not rs: exit() # without first comma print(ins_sql) - print(rs[1:]) + print((rs[1:])) while n > 0: rs = convert(f.readline()) if not rs: exit() diff --git a/agent/structs.py b/agent/structs.py index 55b6e61..f69cb56 100644 --- a/agent/structs.py +++ b/agent/structs.py @@ -1,12 +1,10 @@ # -*- coding: utf8 -*- from abc import ABCMeta, abstractmethod from struct import pack, unpack -from utils import int2ip, ip2int +from .utils import int2ip, ip2int -class BaseStruct(object): - __metaclass__ = ABCMeta - +class BaseStruct(object, metaclass=ABCMeta): @abstractmethod def serialize(self): """привращаем инфу в бинарную строку""" @@ -55,7 +53,7 @@ class TariffStruct(BaseStruct): class AbonStruct(BaseStruct): def __init__(self, uid=None, ip=None, tariff=None): - self.uid = long(uid) + self.uid = int(uid) self.ip = IpStruct(ip) assert isinstance(tariff, TariffStruct) self.tariff = tariff @@ -70,7 +68,7 @@ class AbonStruct(BaseStruct): dt = unpack("!LII", data) self.uid = dt[0] self.ip = IpStruct(dt[1]) - tarifs = filter(lambda trf: trf.tid == dt[2], all_tarifs) + tarifs = [trf for trf in all_tarifs if trf.tid == dt[2]] if len(tarifs) < 1: raise IndexError assert isinstance(tarifs[0], TariffStruct) diff --git a/chatbot/admin.py b/chatbot/admin.py index e8b9ae8..770758e 100644 --- a/chatbot/admin.py +++ b/chatbot/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.MessageHistory) admin.site.register(models.TelegramBot) diff --git a/chatbot/migrations/0001_initial.py b/chatbot/migrations/0001_initial.py index de353d9..2fa3b28 100644 --- a/chatbot/migrations/0001_initial.py +++ b/chatbot/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2017-01-15 20:55 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models diff --git a/chatbot/models.py b/chatbot/models.py index 9adc027..550924f 100644 --- a/chatbot/models.py +++ b/chatbot/models.py @@ -2,11 +2,15 @@ from django.db import models from djing.settings import AUTH_USER_MODEL +class ChatException(Exception): + pass + + class TelegramBot(models.Model): user = models.ForeignKey(AUTH_USER_MODEL) chat_id = models.PositiveIntegerField(default=0) - def __unicode__(self): + def __str__(self): return self.user.get_full_name() + ' - ' + str(self.chat_id) @@ -15,5 +19,5 @@ class MessageHistory(models.Model): message = models.CharField(max_length=255) date_sent = models.DateTimeField(auto_now_add=True) - def __unicode__(self): + def __str__(self): return self.message diff --git a/chatbot/telebot.py b/chatbot/telebot.py index cbfe131..201af45 100755 --- a/chatbot/telebot.py +++ b/chatbot/telebot.py @@ -2,9 +2,10 @@ from telepot import helper, glance, Bot import os import socket -from models import TelegramBot +from .models import TelegramBot, ChatException from chatbot.models import MessageHistory from accounts_app.models import UserProfile +import collections token = '285129725:AAF9Si5_b1n1_cN3vJtwXt0gkgsqKBptut4' @@ -15,7 +16,7 @@ class DjingTelebot(helper.ChatHandler): _chat_id = 0 def __init__(self, seed_tuple, **kwargs): - super(DjingTelebot, self).__init__(seed_tuple, **kwargs) + super().__init__(seed_tuple, **kwargs) self.cmds = { 'ping': self.ping, 'iam': self.say_me @@ -27,7 +28,7 @@ class DjingTelebot(helper.ChatHandler): # задаём вопрос пользователю, и ожидаем ответ в fn def _question(self, text, fn): - assert callable(fn) + assert isinstance(fn, collections.Callable) self._dialog_fn = fn if text is not None: self._sent_reply(text) @@ -55,7 +56,7 @@ class DjingTelebot(helper.ChatHandler): self._current_user = tbot.user self._message_log(initial_msg['text']) except TelegramBot.DoesNotExist: - self._question(u'Давай знакомиться, как тебя зовут? Напиши свой логин из биллинга.', + self._question('Давай знакомиться, как тебя зовут? Напиши свой логин из биллинга.', self.question_name) return True # prevent on_message() from being called on the initial message @@ -68,13 +69,14 @@ class DjingTelebot(helper.ChatHandler): text = msg['text'].lower() # выполняем комманды если они есть - if text in self.cmds.keys(): + if text in list(self.cmds.keys()): self.cmds[text]() elif self._dialog_fn is not None: + assert callable(self._dialog_fn) self._dialog_fn(text) self._dialog_fn = None else: - self._sent_reply(u'Я пока не знаю ответа на это') + self._sent_reply('Я пока не знаю ответа на это') if not self._message_log(text): return @@ -93,10 +95,10 @@ class DjingTelebot(helper.ChatHandler): chat_id=self._chat_id ) except UserProfile.DoesNotExist: - self._question(u'Ты не найден в базе, проверь что правильно указал именно свой ЛОГИН. Попробуй ещё', + self._question('Ты не найден в базе, проверь что правильно указал именно свой ЛОГИН. Попробуй ещё', self.question_name) return - self._sent_reply(u'Да, приятно познакомиться %s, я буду оповещать тебя о событиях в биллинге. Удачной работы ;)' + self._sent_reply('Да, приятно познакомиться %s, я буду оповещать тебя о событиях в биллинге. Удачной работы ;)' % profile.get_full_name()) # заканчивается время диалога @@ -109,22 +111,25 @@ class DjingTelebot(helper.ChatHandler): # пингуем адрес def ping(self, ip=None): if ip is None: - self._question(u'Давай пинганём, напиши ip. Нужно будет подождать 10 сек', self.ping) + self._question('Давай пинганём, напиши ip. Нужно будет подождать 10 сек', self.ping) return try: socket.inet_aton(ip) ret = os.popen('`which ping` -c 10 ' + ip).read() self._sent_reply(ret) except socket.error: - self._question(u'Это не похоже на ip адрес, попробуй ещё', self.ping) + self._question('Это не похоже на ip адрес, попробуй ещё', self.ping) def say_me(self): - self._sent_reply(u'Ты ведь %s ?' % self._current_user.get_full_name()) + self._sent_reply('Ты ведь %s ?' % self._current_user.get_full_name()) # Просто отправляем текст оповещения указанному админу def send_notify(msg_text, account): - tb = TelegramBot.objects.get(user=account) - tbot = Bot(token) - tbot.sendMessage(tb.chat_id, msg_text) - + print(account) + try: + tb = TelegramBot.objects.get(user=account) + tbot = Bot(token) + tbot.sendMessage(tb.chat_id, msg_text) + except TelegramBot.DoesNotExist: + raise ChatException('Цель оповещения не подписан на оповещения') diff --git a/clientsideapp/models.py b/clientsideapp/models.py index 3eff443..b0b75a3 100644 --- a/clientsideapp/models.py +++ b/clientsideapp/models.py @@ -1,3 +1,3 @@ -from __future__ import unicode_literals + # Create your models here. diff --git a/clientsideapp/urls.py b/clientsideapp/urls.py index dd0b107..49ee517 100644 --- a/clientsideapp/urls.py +++ b/clientsideapp/urls.py @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/clientsideapp/views.py b/clientsideapp/views.py index da2f1c4..41c0512 100644 --- a/clientsideapp/views.py +++ b/clientsideapp/views.py @@ -61,21 +61,21 @@ def debt_buy(request, d_id): try: sure = request.POST.get('sure') if sure != 'on': - raise LogicError(u'Вы не уверены что хотите оплатить долг?') + raise LogicError('Вы не уверены что хотите оплатить долг?') if abon.ballance < debt.amount: - raise LogicError(u'Не достаточно средств на счету') + raise LogicError('Не достаточно средств на счету') abon.make_pay(request.user, debt.amount, debt.comment) debt.set_ok() abon.save(update_fields=['ballance']) debt.save(update_fields=['status', 'date_pay']) return redirect('client_side:debts') - except LogicError, e: - messages.error(request, e.value) + except LogicError as e: + messages.error(request, e) except NasFailedResult as e: - messages.error(request, e.message) + messages.error(request, e) except NasNetworkError as e: - messages.error(request, e.message) + messages.error(request, e) return render(request, 'clientsideapp/debt_buy.html', { 'debt': debt, 'amount': debt.amount, diff --git a/devapp/admin.py b/devapp/admin.py index 095381c..e27201c 100644 --- a/devapp/admin.py +++ b/devapp/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.Device) diff --git a/devapp/apps.py b/devapp/apps.py index 1ccacdf..1880f8c 100644 --- a/devapp/apps.py +++ b/devapp/apps.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from django.apps import AppConfig diff --git a/devapp/base_intr.py b/devapp/base_intr.py index 54af5eb..067c50b 100644 --- a/devapp/base_intr.py +++ b/devapp/base_intr.py @@ -3,9 +3,7 @@ from abc import ABCMeta, abstractmethod from netsnmp import Session, VarList, Varbind -class DevBase(object): - __metaclass__ = ABCMeta - +class DevBase(object, metaclass=ABCMeta): @staticmethod def description(): """Возвращает текстовое описание""" @@ -27,9 +25,7 @@ class DevBase(object): pass -class BasePort(object): - __metaclass__ = ABCMeta - +class BasePort(object, metaclass=ABCMeta): def __init__(self, num, name, status, mac, speed): self.num = int(num) self.nm = name @@ -50,8 +46,7 @@ class BasePort(object): return "%x:%x:%x:%x:%x:%x" % (ord(m[0]), ord(m[1]), ord(m[2]), ord(m[3]), ord(m[4]), ord(m[5])) -class SNMPBaseWorker(object): - __metaclass__ = ABCMeta +class SNMPBaseWorker(object, metaclass=ABCMeta): ses = None def __init__(self, ip, community='public', ver=2): diff --git a/devapp/dev_types.py b/devapp/dev_types.py index efd901a..efb91af 100644 --- a/devapp/dev_types.py +++ b/devapp/dev_types.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from mydefs import RuTimedelta, safe_int -from base_intr import DevBase, SNMPBaseWorker, BasePort +from .base_intr import DevBase, SNMPBaseWorker, BasePort @@ -49,7 +49,7 @@ class DLinkDevice(DevBase, SNMPBaseWorker): @staticmethod def description(): - return u"Свич D'Link" + return "Свич D'Link" def reboot(self): pass @@ -61,13 +61,13 @@ class DLinkDevice(DevBase, SNMPBaseWorker): speeds = self.get_list(oids['get_ports']['speeds']) res = [] ln = len(speeds) - for n in range(0, ln): + for n in range(ln): status = True if int(stats[n]) == 1 else False res.append(DLinkPort( n+1, - nams[n] if len(nams) > 0 else u'не получил имя', + nams[n] if len(nams) > 0 else 'не получил имя', status, - macs[n] if len(macs) > 0 else u'не нашёл мак', + macs[n] if len(macs) > 0 else 'не нашёл мак', int(speeds[n]) if len(speeds) > 0 else 0, self)) return res diff --git a/devapp/forms.py b/devapp/forms.py index eae3d4b..4ae1d54 100644 --- a/devapp/forms.py +++ b/devapp/forms.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from django import forms -import models +from . import models from mydefs import ip_addr_regex diff --git a/devapp/migrations/0001_initial.py b/devapp/migrations/0001_initial.py index f005e02..2bf13ba 100644 --- a/devapp/migrations/0001_initial.py +++ b/devapp/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.db import migrations, models import django.db.models.deletion @@ -19,10 +18,10 @@ class Migration(migrations.Migration): name='Device', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ip_address', mydefs.MyGenericIPAddressField(max_length=8, protocol=b'IPv4')), + ('ip_address', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')), ('comment', models.CharField(max_length=256)), ('devtype', - models.CharField(choices=[(b'Dl', "\u0421\u0432\u0438\u0447 D'Link")], default=b'Dl', max_length=2)), + models.CharField(choices=[('Dl', "Свич D'Link")], default='Dl', max_length=2)), ('man_passw', models.CharField(blank=True, max_length=16, null=True)), ], ), @@ -32,7 +31,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('num', models.PositiveSmallIntegerField(default=0)), ('speed', - models.CharField(choices=[(b'h', b'100Mbps'), (b'k', b'1Gbps'), (b'd', b'10Gbps')], default=b'h', + models.CharField(choices=[('h', '100Mbps'), ('k', '1Gbps'), ('d', '10Gbps')], default='h', max_length=1)), ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device')), ], @@ -47,6 +46,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='port', - unique_together=set([('device', 'num')]), + unique_together={('device', 'num')}, ), ] diff --git a/devapp/migrations/0002_auto_20160909_1018.py b/devapp/migrations/0002_auto_20160909_1018.py index 2761747..b1069bb 100644 --- a/devapp/migrations/0002_auto_20160909_1018.py +++ b/devapp/migrations/0002_auto_20160909_1018.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-09-09 07:18 -from __future__ import unicode_literals from django.db import migrations diff --git a/devapp/models.py b/devapp/models.py index 1dd5c09..b0aa97b 100644 --- a/devapp/models.py +++ b/devapp/models.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- from django.db import models -from base_intr import DevBase +from .base_intr import DevBase from mydefs import MyGenericIPAddressField, MyChoicesAdapter -from dev_types import DEVICE_TYPES +from .dev_types import DEVICE_TYPES class _DeviceChoicesAdapter(MyChoicesAdapter): def __init__(self): - super(_DeviceChoicesAdapter, self).__init__(DEVICE_TYPES) + super().__init__(DEVICE_TYPES) class Device(models.Model): @@ -28,15 +28,15 @@ class Device(models.Model): pass def get_manager_klass(self): - klasses = filter(lambda kl: kl[0] == self.devtype, DEVICE_TYPES) + klasses = [kl for kl in DEVICE_TYPES if kl[0] == self.devtype] if len(klasses) > 0: res = klasses[0][1] if issubclass(res, DevBase): return res return - def __unicode__(self): - return u"%s: (%s) %s" % (self.comment, self.get_devtype_display(), self.ip_address) + def __str__(self): + return "%s: (%s) %s" % (self.comment, self.get_devtype_display(), self.ip_address) class Port(models.Model): diff --git a/devapp/tests.py b/devapp/tests.py index 565e169..ee30280 100644 --- a/devapp/tests.py +++ b/devapp/tests.py @@ -1,5 +1,5 @@ from django.test import TestCase -import dev_types +from . import dev_types class DevTest(TestCase): @@ -10,13 +10,13 @@ class DevTest(TestCase): def snmp(self): dev = dev_types.DLinkDevice('10.115.1.105', '', 2) - print('DevName:', dev.get_device_name()) + print(('DevName:', dev.get_device_name())) ports = dev.get_ports() - print 'gports' + print('gports') for port in ports: assert issubclass(port.__class__, dev_types.BasePort) - print('\tPort:', port.nm, port.st, port.mac(), port.sp) + print(('\tPort:', port.nm, port.st, port.mac(), port.sp)) # Disable 2 port - print ports[1].disable() + print((ports[1].disable())) # Enable 2 port - print ports[1].enable() + print((ports[1].enable())) diff --git a/devapp/urls.py b/devapp/urls.py index 6a1e013..9c61c9b 100644 --- a/devapp/urls.py +++ b/devapp/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/devapp/views.py b/devapp/views.py index 3b5335e..72c7fda 100644 --- a/devapp/views.py +++ b/devapp/views.py @@ -4,9 +4,9 @@ from django.core.exceptions import PermissionDenied from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages -from models import Device +from .models import Device from mydefs import pag_mn, res_success, res_error, only_admins, ping -from forms import DeviceForm +from .forms import DeviceForm @login_required @@ -27,7 +27,7 @@ def devdel(request, did): get_object_or_404(Device, id=did).delete() return res_success(request, 'devapp:devs') except: - return res_error(request, u'Неизвестная ошибка при удалении :(') + return res_error(request, 'Неизвестная ошибка при удалении :(') @login_required @@ -47,7 +47,7 @@ def dev(request, devid=0): frm.save() return redirect('devapp:view', did=devid) else: - messages.error(request, u'Ошибка в данных, проверте их ещё раз') + messages.error(request, 'Ошибка в данных, проверте их ещё раз') else: frm = DeviceForm(instance=devinst) @@ -70,9 +70,9 @@ def devview(request, did): uptime = manager.uptime() ports = manager.get_ports() else: - messages.warning(request, u'Не указан snmp пароль для устройства') + messages.warning(request, 'Не указан snmp пароль для устройства') else: - messages.error(request, u'Эта точка не пингуется') + messages.error(request, 'Эта точка не пингуется') return render(request, 'devapp/ports.html', { 'dev': dev, @@ -96,7 +96,7 @@ def toggle_port(request, did, portid, status=0): else: ports[portid-1].disable() else: - messages.warning(request, u'Не указан snmp пароль для устройства') + messages.warning(request, 'Не указан snmp пароль для устройства') else: - messages.error(request, u'Эта точка не пингуется') + messages.error(request, 'Эта точка не пингуется') return redirect('devapp:view', did=did) diff --git a/djing/urls.py b/djing/urls.py index e885060..063c1a1 100644 --- a/djing/urls.py +++ b/djing/urls.py @@ -1,8 +1,8 @@ from django.conf.urls import url, include from django.contrib import admin -import settings -from views import home +from . import settings +from .views import home urlpatterns = [ diff --git a/djing/utils/load_from_nodeny.py b/djing/utils/load_from_nodeny.py index 7e801d0..dfa80e1 100755 --- a/djing/utils/load_from_nodeny.py +++ b/djing/utils/load_from_nodeny.py @@ -24,7 +24,7 @@ if __name__ == "__main__": 'name': res[0], 'fio': res[1], 'tel': res[2], - 'addr': u"ул. %s д. %s" % (res[3], res[4]), + 'addr': "ул. %s д. %s" % (res[3], res[4]), 'birth': int(res[5]), 'grp': int(res[6]) }) diff --git a/djing/utils/push_snmp_passw.py b/djing/utils/push_snmp_passw.py index e4d2dbc..bdbcebc 100644 --- a/djing/utils/push_snmp_passw.py +++ b/djing/utils/push_snmp_passw.py @@ -21,7 +21,7 @@ def cmd(ip): tn.write("save config config_id 1\n") tn.write("log\n") - print(tn.read_all()) + print((tn.read_all())) tn.close() @@ -30,7 +30,7 @@ def prc(ip): if ping(ip): cmd(ip) except error: - print('Error connect to', ip) + print(('Error connect to', ip)) if __name__ == '__main__': diff --git a/djing/utils/save_dot_from_nodeny.py b/djing/utils/save_dot_from_nodeny.py index 1b5dbcb..ddae02c 100644 --- a/djing/utils/save_dot_from_nodeny.py +++ b/djing/utils/save_dot_from_nodeny.py @@ -26,4 +26,4 @@ if __name__ == "__main__": ) dev.comment=dt['loc'] dev.save() - print(dt['descr'], dt['loc'], dev) + print((dt['descr'], dt['loc'], dev)) diff --git a/djing/utils/save_from_nodeny.py b/djing/utils/save_from_nodeny.py index 1a404fc..712ce67 100755 --- a/djing/utils/save_from_nodeny.py +++ b/djing/utils/save_from_nodeny.py @@ -24,7 +24,7 @@ if __name__ == "__main__": dt['obj'] = grp for dt in dat['users']: - grp = filter(lambda gr: dt['grp']==gr['gid'], dat['groups']) + grp = [gr for gr in dat['groups'] if dt['grp']==gr['gid']] grp = grp[0]['obj'] if len(grp)>0 else None try: abon = Abon.objects.get(username=dt['name']) @@ -35,4 +35,4 @@ if __name__ == "__main__": abon.address=dt['addr'] abon.group=grp abon.save() - print(abon.username, abon.fio, abon.group) + print((abon.username, abon.fio, abon.group)) diff --git a/gmap/apps.py b/gmap/apps.py index 7cb7b32..2122372 100644 --- a/gmap/apps.py +++ b/gmap/apps.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from django.apps import AppConfig diff --git a/gmap/migrations/0001_initial.py b/gmap/migrations/0001_initial.py index 19a6bbb..3d949fd 100644 --- a/gmap/migrations/0001_initial.py +++ b/gmap/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-11-30 15:15 -from __future__ import unicode_literals from django.db import migrations, models import django.db.models.deletion @@ -30,7 +29,7 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=200)), ('latitude', models.CharField(blank=True, max_length=30)), ('longitude', models.CharField(blank=True, max_length=30)), - ('platinum', models.BooleanField(default=False, verbose_name=b'Platinum Partner')), + ('platinum', models.BooleanField(default=False, verbose_name='Platinum Partner')), ('contact_name', models.CharField(blank=True, max_length=50)), ('contact_title', models.CharField(blank=True, max_length=50)), ('airport_name', models.CharField(blank=True, max_length=100)), @@ -49,35 +48,35 @@ class Migration(migrations.Migration): name='MarkerCategory', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200, unique=True, verbose_name=b'type')), + ('name', models.CharField(max_length=200, unique=True, verbose_name='type')), ('position', models.IntegerField(default=0)), - ('icon', models.ImageField(blank=True, upload_to=b'gmap-icons/', verbose_name=b'icon')), - ('platinum_icon', models.ImageField(blank=True, upload_to=b'gmap-icons/', verbose_name=b'platinum icon')), - ('shadow', models.ImageField(blank=True, upload_to=b'gmap-icons/', verbose_name=b'icon shadow')), + ('icon', models.ImageField(blank=True, upload_to='gmap-icons/', verbose_name='icon')), + ('platinum_icon', models.ImageField(blank=True, upload_to='gmap-icons/', verbose_name='platinum icon')), + ('shadow', models.ImageField(blank=True, upload_to='gmap-icons/', verbose_name='icon shadow')), ], ), migrations.CreateModel( name='MarkerSubCategory', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200, unique=True, verbose_name=b'Name')), + ('name', models.CharField(max_length=200, unique=True, verbose_name='Name')), ], ), migrations.CreateModel( name='SalesBoundary', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('boundary_code', models.CharField(max_length=75, verbose_name=b'Boundary Code')), + ('boundary_code', models.CharField(max_length=75, verbose_name='Boundary Code')), ], ), migrations.CreateModel( name='SalesDirector', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True, verbose_name=b'Name')), + ('name', models.CharField(max_length=100, unique=True, verbose_name='Name')), ('title', models.CharField(blank=True, max_length=50)), - ('phone', models.CharField(blank=True, max_length=40, verbose_name=b'Phone Number')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name=b'Email')), + ('phone', models.CharField(blank=True, max_length=40, verbose_name='Phone Number')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='Email')), ('airport_code', models.CharField(blank=True, max_length=8)), ('airport_name', models.CharField(blank=True, max_length=50)), ('address', models.TextField(blank=True, max_length=200)), @@ -110,6 +109,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='salesboundary', - unique_together=set([('boundary_code', 'owner')]), + unique_together={('boundary_code', 'owner')}, ), ] diff --git a/gmap/models.py b/gmap/models.py index d16cdaa..18c29a7 100644 --- a/gmap/models.py +++ b/gmap/models.py @@ -3,41 +3,41 @@ from django.db import models from gmap.utils import geolocate -CATEGORY_LOOKUP = {u'1': 'Cirrus Authorized Service Center (ASC)', u'2': 'Cirrus Sales Representative or Center', - u'3': 'Cirrus Training Center (CTC)', u'4': 'Cirrus Standardized Instructor Pilot (CSIP)'} +CATEGORY_LOOKUP = {'1': 'Cirrus Authorized Service Center (ASC)', '2': 'Cirrus Sales Representative or Center', + '3': 'Cirrus Training Center (CTC)', '4': 'Cirrus Standardized Instructor Pilot (CSIP)'} -INVERSE_CATEGORY = dict((v, k) for k, v in CATEGORY_LOOKUP.iteritems()) +INVERSE_CATEGORY = dict((v, k) for k, v in CATEGORY_LOOKUP.items()) SUBCATEGORY_LOOKUP = { - u'1': 'Composite & Paint Repair', - u'2': 'Pickup & Delivery Service', - u'3': 'Parts Distributor', - u'4': 'Air Conditioning Service', - u'5': 'Garmin Service', - u'6': 'Avidyne Service', - u'7': 'Full Avionics Facility', - u'8': 'Oxygen Service', - u'9': 'Wi-Fi Equipped', - u'10': 'CAPS Overhaul', - u'11': 'Cirrus Platinum Service Partner', - u'12': 'Ice Protection System Maintenance', - u'13': 'SR20 Rental', - u'14': 'SR22 Rental', - u'15': 'SR22T Rental', - u'16': 'Cirrus Perspective Avionics Available', - u'17': 'Avidyne Entegra Avionics Available', - u'18': 'Cirrus Platinum Training Partner', - u'19': 'Simulator Available', - u'20': 'Cirrus Perspective Qualified', - u'21': 'Avidyne Entegra Qualified', - u'22': 'New Cirrus Sales', - u'23': 'Used Cirrus Sales', - u'24': 'n/a' + '1': 'Composite & Paint Repair', + '2': 'Pickup & Delivery Service', + '3': 'Parts Distributor', + '4': 'Air Conditioning Service', + '5': 'Garmin Service', + '6': 'Avidyne Service', + '7': 'Full Avionics Facility', + '8': 'Oxygen Service', + '9': 'Wi-Fi Equipped', + '10': 'CAPS Overhaul', + '11': 'Cirrus Platinum Service Partner', + '12': 'Ice Protection System Maintenance', + '13': 'SR20 Rental', + '14': 'SR22 Rental', + '15': 'SR22T Rental', + '16': 'Cirrus Perspective Avionics Available', + '17': 'Avidyne Entegra Avionics Available', + '18': 'Cirrus Platinum Training Partner', + '19': 'Simulator Available', + '20': 'Cirrus Perspective Qualified', + '21': 'Avidyne Entegra Qualified', + '22': 'New Cirrus Sales', + '23': 'Used Cirrus Sales', + '24': 'n/a' } -INVERSE_SUBCATEGORY = dict((v, k) for k, v in SUBCATEGORY_LOOKUP.iteritems()) +INVERSE_SUBCATEGORY = dict((v, k) for k, v in SUBCATEGORY_LOOKUP.items()) # name, category, platinum partner, contacT_name, contact_title, airport_name, airport_code, address, phone, fax, email, url, sub_category1, ..., sub_categoryN @@ -60,7 +60,7 @@ class SalesBoundary(models.Model): class Meta: unique_together = ("boundary_code", "owner") - def __unicode__(self): + def __str__(self): return self.boundary_code @@ -146,7 +146,7 @@ class SalesDirector(models.Model): # Ask django really, really nicely not to insert our object twice self.save() - def __unicode__(self): + def __str__(self): return self.name @@ -166,7 +166,7 @@ class MarkerCategory(models.Model): def natural_key(self): return self.name - def __unicode__(self): + def __str__(self): return self.name @@ -177,7 +177,7 @@ class MarkerSubCategory(models.Model): def natural_key(self): return self.name - def __unicode__(self): + def __str__(self): return self.name @@ -198,7 +198,7 @@ class CountryISOCode(models.Model): def natural_key(self): return self.long_name - def __unicode__(self): + def __str__(self): return self.long_name @@ -237,9 +237,9 @@ class MapMarker(models.Model): else: raise GeolocateFailure("Failed to geolocate address for %s" % self.name, full_address) - super(MapMarker, self).save(*args, **kwargs) + super().save(*args, **kwargs) - def __unicode__(self): + def __str__(self): return self.name def from_csv(self, row, row_id, errors): diff --git a/gmap/utils.py b/gmap/utils.py index eb64485..82b71d3 100644 --- a/gmap/utils.py +++ b/gmap/utils.py @@ -1,15 +1,15 @@ import json -import urllib -import urllib2 +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse import csv import codecs -import cStringIO +import io def csvByLine(csvFile, lineHandler): errors = '' for row_id, line in enumerate(UnicodeReader(csvFile)): - print "Calling Line handler for %s" % line + print(("Calling Line handler for %s" % line)) errors = ''.join([errors, lineHandler(line)]) return errors @@ -28,8 +28,8 @@ def geolocate(location, sensor=False): """ sensor = str(sensor).lower() url = "http://maps.googleapis.com/maps/api/geocode/json?" - url += urllib.urlencode({'address': location, 'sensor': sensor}) - data = urllib2.urlopen(url).read() + url += urllib.parse.urlencode({'address': location, 'sensor': sensor}) + data = urllib.request.urlopen(url).read() data = json.loads(data) if data and data['status'] == 'OK': return ({ @@ -43,10 +43,10 @@ def geolocate(location, sensor=False): def georeverse(lat, lon): # construct url for reverse geocoding with google-maps url = "http://maps.googleapis.com/maps/api/geocode/json?" - url += urllib.urlencode({'latlng': lat + ',' + lon, 'sensor': 'false'}) + url += urllib.parse.urlencode({'latlng': lat + ',' + lon, 'sensor': 'false'}) # retrieve and load google-map data - data = urllib2.urlopen(url).read() + data = urllib.request.urlopen(url).read() data = json.loads(data) # if request goes through, return the state and country of the location @@ -89,7 +89,7 @@ class UTF8Recoder: def __iter__(self): return self - def next(self): + def __next__(self): # return self.reader.next().decode("cp1252").encode("utf-8") return self.reader.next().encode("utf-8") @@ -105,9 +105,9 @@ class UnicodeReader: f = UTF8Recoder(f, encoding) self.reader = csv.reader(f, dialect=dialect, **kwds) - def next(self): - row = self.reader.next() - return [unicode(s, "utf-8") for s in row] + def __next__(self): + row = next(self.reader) + return [str(s, "utf-8") for s in row] def __iter__(self): return self @@ -121,7 +121,7 @@ class UnicodeWriter: def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): # Redirect output to a queue - self.queue = cStringIO.StringIO() + self.queue = io.StringIO() self.writer = csv.writer(self.queue, dialect=dialect, **kwds) self.stream = f self.encoder = codecs.getincrementalencoder(encoding)() diff --git a/gmap/views.py b/gmap/views.py index cfbd482..98d9c06 100644 --- a/gmap/views.py +++ b/gmap/views.py @@ -103,7 +103,7 @@ def gmap_search(request): def dump_csv(request): all_markers = MapMarker.objects.all() - print '# markers: ', len(all_markers) + print(('# markers: ', len(all_markers))) # all_markers should now have all the things... response = HttpResponse(mimetype='text/csv') @@ -179,7 +179,7 @@ def process_row(row_id, row, errors): def read_csv(request): - if request.method == 'POST' and request.FILES.has_key('datafile'): + if request.method == 'POST' and 'datafile' in request.FILES: # it's conceivable the user could upload a file large enough # it gets split into chunks - to handle this we just direct all diff --git a/ip_pool/admin.py b/ip_pool/admin.py index da36fb5..e98d823 100644 --- a/ip_pool/admin.py +++ b/ip_pool/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.IpPoolItem) diff --git a/ip_pool/apps.py b/ip_pool/apps.py index b5b1b03..8b8d232 100644 --- a/ip_pool/apps.py +++ b/ip_pool/apps.py @@ -3,4 +3,4 @@ from django.apps import AppConfig class IpPoolConfig(AppConfig): name = 'ip_pool' - verbose_name = u"Ip pool" + verbose_name = "Ip pool" diff --git a/ip_pool/forms.py b/ip_pool/forms.py index c5bd8ab..0e6f43f 100644 --- a/ip_pool/forms.py +++ b/ip_pool/forms.py @@ -5,17 +5,17 @@ from mydefs import ip_addr_regex class PoolForm(forms.Form): - start_ip = forms.GenericIPAddressField(protocol='IPv4', widget=forms.TextInput(attrs={ + start_ip = forms.GenericIPAddressField(protocol='ipv4', widget=forms.TextInput(attrs={ 'pattern': ip_addr_regex, - 'placeholder': u'127.0.0.1', + 'placeholder': '127.0.0.1', 'id': 'start_ip', 'class': 'form-control', 'required': '' }), required=True) - end_ip = forms.GenericIPAddressField(protocol='IPv4', widget=forms.TextInput(attrs={ + end_ip = forms.GenericIPAddressField(protocol='ipv4', widget=forms.TextInput(attrs={ 'pattern': ip_addr_regex, - 'placeholder': u'127.0.0.1', + 'placeholder': '127.0.0.1', 'id': 'end_ip', 'class': 'form-control', 'required': '' diff --git a/ip_pool/migrations/0001_initial.py b/ip_pool/migrations/0001_initial.py index 1edd3ec..fa5fcad 100644 --- a/ip_pool/migrations/0001_initial.py +++ b/ip_pool/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.db import migrations, models @@ -18,7 +17,7 @@ class Migration(migrations.Migration): name='IpPoolItem', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ip', mydefs.MyGenericIPAddressField(max_length=8, protocol=b'IPv4')), + ('ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')), ], ), ] diff --git a/ip_pool/models.py b/ip_pool/models.py index 6bdc7a8..d76e56b 100644 --- a/ip_pool/models.py +++ b/ip_pool/models.py @@ -29,9 +29,9 @@ class IpPoolItemManager(models.Manager): end_ip = ip2int(end_ip) if (end_ip - start_ip) > 5000: - raise Exception(u'Not add over 5000 ip\'s') + raise Exception('Not add over 5000 ip\'s') - sql_strs = map(lambda tip: r"(%d)" % tip, range(start_ip, end_ip + 1)) + sql_strs = [r"(%d)" % tip for tip in range(start_ip, end_ip + 1)] sql = r'INSERT INTO ip_pool_ippoolitem (ip) VALUES %s' % r",".join(sql_strs) cursor = connection.cursor() @@ -55,5 +55,5 @@ class IpPoolItem(models.Model): def int_ip(self): return ip2int(self.ip) - def __unicode__(self): + def __str__(self): return self.ip diff --git a/ip_pool/urls.py b/ip_pool/urls.py index 8fcd3fc..de54c47 100644 --- a/ip_pool/urls.py +++ b/ip_pool/urls.py @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/ip_pool/views.py b/ip_pool/views.py index 9e2d947..001bf03 100644 --- a/ip_pool/views.py +++ b/ip_pool/views.py @@ -3,8 +3,8 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages -from forms import PoolForm -from models import IpPoolItem +from .forms import PoolForm +from .models import IpPoolItem import mydefs @@ -14,7 +14,7 @@ def home(request): pools = IpPoolItem.objects.get_pools() if pools: - pools = map(lambda ip: (mydefs.int2ip(ip[0]), mydefs.int2ip(ip[1]), ip[2]), pools) + pools = [(mydefs.int2ip(ip[0]), mydefs.int2ip(ip[1]), ip[2]) for ip in pools] pools = mydefs.pag_mn(request, pools) return render(request, 'ip_pool/index.html', { @@ -65,7 +65,7 @@ def add_pool(request): IpPoolItem.objects.add_pool(cd['start_ip'], cd['end_ip']) return redirect('ip_pool:home') else: - messages.error(request, u'Исправьте ошибки') + messages.error(request, 'Исправьте ошибки') else: frm = PoolForm() return render(request, 'ip_pool/add_pool.html', { diff --git a/manage.py b/manage.py index 0c6d1f0..2a71f0d 100755 --- a/manage.py +++ b/manage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys diff --git a/mydefs.py b/mydefs.py index 6e3111e..68f3709 100644 --- a/mydefs.py +++ b/mydefs.py @@ -73,13 +73,13 @@ def pag_mn(request, objs, count_per_page=PAGINATION_ITEMS_PER_PAGE): class MyGenericIPAddressField(models.GenericIPAddressField): description = "Int32 notation ip address" - def __init__(self, protocol='IPv4', *args, **kwargs): - super(MyGenericIPAddressField, self).__init__(protocol=protocol, *args, **kwargs) + def __init__(self, protocol='ipv4', *args, **kwargs): + super().__init__(protocol=protocol, *args, **kwargs) self.max_length = 8 def get_prep_value(self, value): # strIp to Int - value = super(models.GenericIPAddressField, self).get_prep_value(value) + value = super().get_prep_value(value) return ip2int(value) def to_python(self, addr): @@ -106,7 +106,7 @@ class MyChoicesAdapter(Iterator): self._max_index = len(choices) self.chs = choices - def next(self): + def __next__(self): if self.current_index >= self._max_index: raise StopIteration else: @@ -121,19 +121,19 @@ class MyChoicesAdapter(Iterator): # через get должно быть передано order_by=<поле в бд> а в dir= направление сортировки # возвращает новое направление сортировки и поле для сортировки с направлением def order_helper(request): - dir = request.GET.get('dir') + dr = request.GET.get('dir') dfx = '' - if dir == 'down': - dir = 'up' + if dr == 'down': + dr = 'up' dfx = '-' else: - dir = 'down' + dr = 'down' orby = request.GET.get('order_by') if orby: - return dir, dfx + orby + return dr, dfx + orby else: - return dir, orby + return dr, orby # Декоратор проверяет аккаунт, чтоб не пускать клиентов в страницы администрации @@ -155,10 +155,7 @@ def ping(hostname): # Русифицированный вывод timedelta class RuTimedelta(timedelta): - def __init__(self, *args, **kwargs): - super(RuTimedelta, self).__init__(*args, **kwargs) - - def __unicode__(self): + def __str__(self): hours, remainder = divmod(self.seconds, 3600) minutes, seconds = divmod(remainder, 60) text_date = "%d:%d:%d" % ( @@ -167,10 +164,10 @@ class RuTimedelta(timedelta): seconds ) if self.days > 1: - ru_days = u'дней' + ru_days = 'дней' if 5 > self.days > 1: - ru_days = u'дня' + ru_days = 'дня' elif self.days == 1: - ru_days = u'день' - text_date = u'%d %s %s' % (self.days, ru_days, text_date) + ru_days = 'день' + text_date = '%d %s %s' % (self.days, ru_days, text_date) return text_date diff --git a/photo_app/admin.py b/photo_app/admin.py index e9bc8f2..b5d50f5 100644 --- a/photo_app/admin.py +++ b/photo_app/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.Photo) \ No newline at end of file diff --git a/photo_app/migrations/0001_initial.py b/photo_app/migrations/0001_initial.py index 4ae06a5..2a4206d 100644 --- a/photo_app/migrations/0001_initial.py +++ b/photo_app/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.db import migrations, models @@ -16,8 +15,8 @@ class Migration(migrations.Migration): name='Photo', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('image', models.ImageField(height_field=b'heigt', upload_to=b'', width_field=b'wdth')), - ('wdth', models.PositiveSmallIntegerField(blank=True, default=b'759', editable=False, null=True)), + ('image', models.ImageField(height_field='heigt', upload_to='', width_field='wdth')), + ('wdth', models.PositiveSmallIntegerField(blank=True, default='759', editable=False, null=True)), ('heigt', models.PositiveSmallIntegerField(blank=True, editable=False, null=True)), ], ), diff --git a/photo_app/models.py b/photo_app/models.py index f09ca67..047a92f 100644 --- a/photo_app/models.py +++ b/photo_app/models.py @@ -14,7 +14,7 @@ class Photo(models.Model): wdth = models.PositiveSmallIntegerField(null=True, blank=True, editable=False, default="759") heigt = models.PositiveSmallIntegerField(null=True, blank=True, editable=False) - def __unicode__(self): + def __str__(self): return "{0}".format(self.image) def big(self): @@ -28,7 +28,7 @@ class Photo(models.Model): if not self.image: return - super(Photo, self).save() + super().save() im = Image.open(self.image.path) im.thumbnail((759, 759), Image.ANTIALIAS) @@ -40,7 +40,7 @@ class Photo(models.Model): im.save(fname) os.remove(self.image.path) self.image = "%s.%s" % (hs, ext) - super(Photo, self).save() + super().save() # class Meta: diff --git a/privatemessage/admin.py b/privatemessage/admin.py index fd83d67..cc01895 100644 --- a/privatemessage/admin.py +++ b/privatemessage/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from models import PrivateMessages, Dialog +from .models import PrivateMessages, Dialog admin.site.register(PrivateMessages) diff --git a/privatemessage/context_processors.py b/privatemessage/context_processors.py index 25b8c81..adfab5b 100644 --- a/privatemessage/context_processors.py +++ b/privatemessage/context_processors.py @@ -1,4 +1,4 @@ -from models import PrivateMessages +from .models import PrivateMessages def avail_messages(request): diff --git a/privatemessage/migrations/0001_initial.py b/privatemessage/migrations/0001_initial.py index 6ace03e..469b0e1 100644 --- a/privatemessage/migrations/0001_initial.py +++ b/privatemessage/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models diff --git a/privatemessage/models.py b/privatemessage/models.py index dcdc944..afc6a65 100644 --- a/privatemessage/models.py +++ b/privatemessage/models.py @@ -17,7 +17,7 @@ class Dialog(models.Model): recepient = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+') date_create = models.DateTimeField(auto_now_add=True) - def __unicode__(self): + def __str__(self): return self.title @@ -29,5 +29,5 @@ class PrivateMessages(models.Model): objects = MessagesManager() - def __unicode__(self): + def __str__(self): return self.text diff --git a/privatemessage/tests.py b/privatemessage/tests.py index 28efefa..ce3f289 100644 --- a/privatemessage/tests.py +++ b/privatemessage/tests.py @@ -1,7 +1,7 @@ from django.test import TestCase from django.contrib.auth.models import User -import models +from . import models class PaysTest(TestCase): diff --git a/privatemessage/urls.py b/privatemessage/urls.py index 7d76c80..ac2cace 100644 --- a/privatemessage/urls.py +++ b/privatemessage/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/privatemessage/views.py b/privatemessage/views.py index 888f3bf..2ec4f65 100644 --- a/privatemessage/views.py +++ b/privatemessage/views.py @@ -8,7 +8,7 @@ from django.http import HttpResponse from django.template.context_processors import csrf from django.contrib.auth import get_user_model -from models import PrivateMessages +from .models import PrivateMessages import mydefs @@ -24,13 +24,13 @@ def home(request): @login_required @mydefs.only_admins def delitem(request, id=0): - r = {'errnum': 0, 'errtext': u''} + r = {'errnum': 0, 'errtext': ''} try: PrivateMessages.objects.get(id=id).delete() except PrivateMessages.DoesNotExist: r = { 'errnum': 1, - 'errtext': u'Error while deleting, item does not exist' + 'errtext': 'Error while deleting, item does not exist' } return HttpResponse(dumps(r)) @@ -55,6 +55,6 @@ def send_message(request): msg.save() return redirect('privmsg:home') except UserModel.DoesNotExist: - return mydefs.res_error(request, u'Адресат не найден') + return mydefs.res_error(request, 'Адресат не найден') else: - return mydefs.res_error(request, u'Ошибка типа запроса') + return mydefs.res_error(request, 'Ошибка типа запроса') diff --git a/requirements.txt b/requirements.txt index 9071e7b..c9e2ced 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Django==1.9 Pillow MySQL-python telepot +python3-netsnmp diff --git a/searchapp/apps.py b/searchapp/apps.py index 6cc6464..3d549bf 100644 --- a/searchapp/apps.py +++ b/searchapp/apps.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from django.apps import AppConfig diff --git a/searchapp/models.py b/searchapp/models.py index 3eff443..b0b75a3 100644 --- a/searchapp/models.py +++ b/searchapp/models.py @@ -1,3 +1,3 @@ -from __future__ import unicode_literals + # Create your models here. diff --git a/searchapp/urls.py b/searchapp/urls.py index f07ce5f..a955e6c 100644 --- a/searchapp/urls.py +++ b/searchapp/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/statistics/admin.py b/statistics/admin.py index 85f187a..d39e50b 100644 --- a/statistics/admin.py +++ b/statistics/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.StatElem) diff --git a/statistics/migrations/0001_initial.py b/statistics/migrations/0001_initial.py index 8d8c6be..e5b2f82 100644 --- a/statistics/migrations/0001_initial.py +++ b/statistics/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.db import migrations, models @@ -18,8 +17,8 @@ class Migration(migrations.Migration): name='StatElem', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('src_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol=b'IPv4')), - ('dst_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol=b'IPv4')), + ('src_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')), + ('dst_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')), ('proto', models.PositiveSmallIntegerField(default=0)), ('src_port', models.PositiveIntegerField(default=0)), ('dst_port', models.PositiveIntegerField(default=0)), diff --git a/statistics/models.py b/statistics/models.py index 1856dec..93602e7 100644 --- a/statistics/models.py +++ b/statistics/models.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from django.db import models diff --git a/statistics/urls.py b/statistics/urls.py index 4f30d5e..7d2a74a 100644 --- a/statistics/urls.py +++ b/statistics/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/tariff_app/admin.py b/tariff_app/admin.py index c0ec005..de4701a 100644 --- a/tariff_app/admin.py +++ b/tariff_app/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.Tariff) diff --git a/tariff_app/base_intr.py b/tariff_app/base_intr.py index abb3caa..93bb43f 100644 --- a/tariff_app/base_intr.py +++ b/tariff_app/base_intr.py @@ -3,11 +3,7 @@ from abc import ABCMeta, abstractmethod # from abonapp import Abon -class TariffBase: - __metaclass__ = ABCMeta - - # Принимает на вход: - # abon_tariff - models.AbonTariff object +class TariffBase(metaclass=ABCMeta): @abstractmethod def calc_amount(self, abon_tariff): """Считает итоговую сумму платежа""" diff --git a/tariff_app/custom_tariffs.py b/tariff_app/custom_tariffs.py index fafcc9a..8693ddc 100644 --- a/tariff_app/custom_tariffs.py +++ b/tariff_app/custom_tariffs.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from django.utils import timezone -from base_intr import TariffBase +from .base_intr import TariffBase # from abonapp import AbonTariff @@ -33,7 +33,7 @@ class TariffDefault(TariffBase): @staticmethod def description(): - return u'Базовый расчётный функционал' + return 'Базовый расчётный функционал' class TariffDp(TariffBase): @@ -45,7 +45,7 @@ class TariffDp(TariffBase): @staticmethod def description(): - return u'Как в IS' + return 'Как в IS' class TariffCp(TariffBase): @@ -54,7 +54,7 @@ class TariffCp(TariffBase): @staticmethod def description(): - return u'Пользовательский' + return 'Пользовательский' # Первый - всегда по умолчанию diff --git a/tariff_app/forms.py b/tariff_app/forms.py index ff9f107..bf1fd14 100644 --- a/tariff_app/forms.py +++ b/tariff_app/forms.py @@ -1,6 +1,6 @@ from django import forms -import models +from . import models class TariffForm(forms.ModelForm): diff --git a/tariff_app/migrations/0001_initial.py b/tariff_app/migrations/0001_initial.py index 22ed86b..db6e647 100644 --- a/tariff_app/migrations/0001_initial.py +++ b/tariff_app/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-06-28 23:51 -from __future__ import unicode_literals from django.db import migrations, models @@ -21,11 +20,10 @@ class Migration(migrations.Migration): ('speedOut', models.FloatField(default=0.0)), ('amount', models.FloatField(default=0.0)), ('time_of_action', models.IntegerField(default=30)), - ('calc_type', models.CharField(choices=[(b'Df', - '\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0440\u0430\u0441\u0447\u0451\u0442\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b'), - (b'Dp', '\u041a\u0430\u043a \u0432 IS'), (b'Cp', - '\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439')], - default=b'Df', max_length=2)), + ('calc_type', models.CharField(choices=[('Df', 'Базовый расчётный функционал'), + ('Dp', 'Как в IS'), + ('Cp', 'Пользовательский')], + default='Df', max_length=2)), ], ), ] diff --git a/tariff_app/migrations/0002_tariff_descr.py b/tariff_app/migrations/0002_tariff_descr.py index b841cb3..9083716 100644 --- a/tariff_app/migrations/0002_tariff_descr.py +++ b/tariff_app/migrations/0002_tariff_descr.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-10-25 22:54 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/tariff_app/models.py b/tariff_app/models.py index 406fe2c..f177a45 100644 --- a/tariff_app/models.py +++ b/tariff_app/models.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from django.db import models -from custom_tariffs import TariffBase, TARIFF_CHOICES +from .custom_tariffs import TariffBase, TARIFF_CHOICES from mydefs import MyChoicesAdapter @@ -10,7 +10,7 @@ from mydefs import MyChoicesAdapter class _TariffChoicesAdapter(MyChoicesAdapter): # На вход принимает кортеж кортежей, вложенный из 2х элементов: кода и класса, как: TARIFF_CHOICES def __init__(self): - super(_TariffChoicesAdapter, self).__init__(TARIFF_CHOICES) + super().__init__(TARIFF_CHOICES) class Tariff(models.Model): @@ -24,11 +24,11 @@ class Tariff(models.Model): # Возвращает потомок класса TariffBase, методы которого дают нужную логику оплаты по тарифу def get_calc_type(self): - ob = filter(lambda TC: TC[0] == self.calc_type, TARIFF_CHOICES) + ob = [TC for TC in TARIFF_CHOICES if TC[0] == self.calc_type] if len(ob) > 0: res_type = ob[0][1] assert issubclass(res_type, TariffBase) return res_type() - def __unicode__(self): - return u"%s (%f)" % (self.title, self.amount) + def __str__(self): + return "%s (%f)" % (self.title, self.amount) diff --git a/tariff_app/urls.py b/tariff_app/urls.py index 1b74d4f..7df7bf5 100644 --- a/tariff_app/urls.py +++ b/tariff_app/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/tariff_app/views.py b/tariff_app/views.py index 95ee66c..8126e75 100644 --- a/tariff_app/views.py +++ b/tariff_app/views.py @@ -4,9 +4,9 @@ from django.shortcuts import render, get_object_or_404, redirect from django.contrib import messages from django.core.exceptions import PermissionDenied -from models import Tariff +from .models import Tariff import mydefs -import forms +from . import forms @login_required @@ -45,7 +45,7 @@ def edit_tarif(request, tarif_id=0): frm.save() return redirect('tarifs:home') else: - messages.warning(request, u'Не все поля заполнены правильно, проверте и попробуйте ещё раз') + messages.warning(request, 'Не все поля заполнены правильно, проверте и попробуйте ещё раз') else: if tarif_id == 0: tarif = Tariff() diff --git a/taskapp/admin.py b/taskapp/admin.py index 885ad97..48105b6 100644 --- a/taskapp/admin.py +++ b/taskapp/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -import models +from . import models admin.site.register(models.Task) diff --git a/taskapp/forms.py b/taskapp/forms.py index f56e1dc..38897e9 100644 --- a/taskapp/forms.py +++ b/taskapp/forms.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from datetime import datetime, timedelta from django import forms -from models import Task +from .models import Task class TaskFrm(forms.ModelForm): @@ -11,7 +11,7 @@ class TaskFrm(forms.ModelForm): exclude = ['time_of_create', 'author', 'recipients', 'device'] widgets = { 'descr': forms.TextInput(attrs={ - 'placeholder': u'Краткое описание', + 'placeholder': 'Краткое описание', 'class': "form-control", 'autofocus': '' }), diff --git a/taskapp/handle.py b/taskapp/handle.py index c7f0aa3..706e5b3 100644 --- a/taskapp/handle.py +++ b/taskapp/handle.py @@ -1,27 +1,35 @@ # -*- coding: utf-8 -*- from chatbot.telebot import send_notify +from chatbot.models import ChatException + + +class TaskException(Exception): + pass def handle(task, author, recipient, abon_group): - dst_account = recipient - text = u'Задача' - # Если сигнал самому себе то молчим - if author == recipient: - return - # Если задача 'На выполнении' то молчим - if task.state == b'C': - return - # Если задача завершена - elif task.state == b'F': - text = u'Задача завершена' - # Меняем телефон назначения на телефон автора, т.к. при завершении - # идёт оповещение автору о выполнении - dst_account = author - fulltext=u"%s: %s. " % (text, task.abon.get_full_name()) - if task.abon: - fulltext += u"по адресу %s тел. %s. " % ( - task.abon.address, task.abon.telephone - ) - fulltext += u"с. %s. Тип задачи - %s. " % (abon_group.title, task.get_mode_display()) - fulltext += task.descr if task.descr else u'<без описания>' - send_notify(fulltext, dst_account) + try: + dst_account = recipient + text = 'Задача' + # Если сигнал самому себе то молчим + if author == recipient: + return + # Если задача 'На выполнении' то молчим + if task.state == 'C': + return + # Если задача завершена + elif task.state == 'F': + text = 'Задача завершена' + # Меняем телефон назначения на телефон автора, т.к. при завершении + # идёт оповещение автору о выполнении + dst_account = author + fulltext="%s: %s. " % (text, task.abon.get_full_name()) + if task.abon: + fulltext += "по адресу %s тел. %s. " % ( + task.abon.address, task.abon.telephone + ) + fulltext += "с. %s. Тип задачи - %s. " % (abon_group.title, task.get_mode_display()) + fulltext += task.descr if task.descr else '<без описания>' + send_notify(fulltext, dst_account) + except ChatException as e: + raise TaskException(e) diff --git a/taskapp/migrations/0001_initial.py b/taskapp/migrations/0001_initial.py index 96ab114..ffd281f 100644 --- a/taskapp/migrations/0001_initial.py +++ b/taskapp/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-09-09 07:18 -from __future__ import unicode_literals import taskapp.models from django.conf import settings @@ -23,7 +22,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('descr', models.CharField(max_length=128)), - ('priority', models.CharField(choices=[(b'A', '\u0412\u044b\u0441\u0448\u0438\u0439'), (b'B', '\u0412\u044b\u0448\u0435 \u0441\u0440\u0435\u0434\u043d\u0435\u0433\u043e'), (b'C', '\u0421\u0440\u0435\u0434\u043d\u0438\u0439'), (b'D', '\u041d\u0438\u0436\u0435 \u0441\u0440\u0435\u0434\u043d\u0435\u0433\u043e'), (b'E', '\u041d\u0438\u0437\u043a\u0438\u0439')], default=b'C', max_length=1)), + ('priority', models.CharField(choices=[('A', 'Высший'), ('B', 'Выше среднего'), ('C', 'Средний'), ('D', 'Ниже среднего'), ('E', 'Низкий')], default='C', max_length=1)), ('out_date', models.DateField(blank=True, default=taskapp.models._delta_add_days, null=True)), ('time_of_create', models.DateTimeField(auto_now_add=True)), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)), diff --git a/taskapp/migrations/0002_auto_20161006_0027.py b/taskapp/migrations/0002_auto_20161006_0027.py index cf76cc5..e582ac5 100644 --- a/taskapp/migrations/0002_auto_20161006_0027.py +++ b/taskapp/migrations/0002_auto_20161006_0027.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-10-05 21:27 -from __future__ import unicode_literals from django.db import migrations, models @@ -19,6 +18,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='task', name='state', - field=models.CharField(choices=[(b'S', '\u041d\u043e\u0432\u0430\u044f'), (b'C', '\u041d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438'), (b'F', '\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430')], default=b'S', max_length=1), + field=models.CharField(choices=[('S', 'Новая'), ('C', 'На выполнении'), ('F', 'Выполнена')], default='S', max_length=1), ) ] diff --git a/taskapp/migrations/0003_auto_20161130_1815.py b/taskapp/migrations/0003_auto_20161130_1815.py index 014ed66..fe83875 100644 --- a/taskapp/migrations/0003_auto_20161130_1815.py +++ b/taskapp/migrations/0003_auto_20161130_1815.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-11-30 15:15 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/taskapp/migrations/0004_auto_20161202_1230.py b/taskapp/migrations/0004_auto_20161202_1230.py index 4208dbc..dae573c 100644 --- a/taskapp/migrations/0004_auto_20161202_1230.py +++ b/taskapp/migrations/0004_auto_20161202_1230.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-02 09:30 -from __future__ import unicode_literals from django.db import migrations, models @@ -15,6 +14,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='task', name='mode', - field=models.CharField(choices=[(b'na', '\u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e'), (b'yt', '\u0436\u0451\u043b\u0442\u044b\u0439 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a'), (b'rc', '\u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u043a\u0440\u0435\u0441\u0442\u0438\u043a'), (b'ls', '\u0441\u043b\u0430\u0431\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c'), (b'cf', '\u043e\u0431\u0440\u044b\u0432 \u043a\u0430\u0431\u0435\u043b\u044f'), (b'cn', '\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435'), (b'pf', '\u043f\u0435\u0440\u0435\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435'), (b'cr', '\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u043e\u0443\u0442\u0435\u0440\u0430'), (b'ot', '\u0434\u0440\u0443\u0433\u043e\u0435')], default=b'na', max_length=2), + field=models.CharField(choices=[('na', 'не выбрано'), ('yt', 'жёлтый треугольник'), ('rc', 'красный крестик'), ('ls', 'слабая скорость'), ('cf', 'обрыв кабеля'), ('cn', 'подключение'), ('pf', 'переодическое пропадание'), ('cr', 'настройка роутера'), ('ot', 'другое')], default='na', max_length=2), ) ] diff --git a/taskapp/migrations/0005_auto_20161206_0013.py b/taskapp/migrations/0005_auto_20161206_0013.py index b2c8c36..8891a9b 100644 --- a/taskapp/migrations/0005_auto_20161206_0013.py +++ b/taskapp/migrations/0005_auto_20161206_0013.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-05 21:13 -from __future__ import unicode_literals from django.db import migrations, models import django.db.models.deletion diff --git a/taskapp/migrations/0006_auto_20161206_2135.py b/taskapp/migrations/0006_auto_20161206_2135.py index e25b9a5..0d446e6 100644 --- a/taskapp/migrations/0006_auto_20161206_2135.py +++ b/taskapp/migrations/0006_auto_20161206_2135.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-06 18:35 -from __future__ import unicode_literals from django.db import migrations, models @@ -15,11 +14,11 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='task', name='mode', - field=models.CharField(choices=[(b'na', '\u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e'), (b'yt', '\u0436\u0451\u043b\u0442\u044b\u0439 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a'), (b'rc', '\u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u043a\u0440\u0435\u0441\u0442\u0438\u043a'), (b'ls', '\u0441\u043b\u0430\u0431\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c'), (b'cf', '\u043e\u0431\u0440\u044b\u0432 \u043a\u0430\u0431\u0435\u043b\u044f'), (b'cn', '\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435'), (b'pf', '\u043f\u0435\u0440\u0435\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435'), (b'cr', '\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u043e\u0443\u0442\u0435\u0440\u0430'), (b'co', '\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c onu'), (b'fc', '\u043e\u0431\u0436\u0430\u0442\u044c \u043a\u0430\u0431\u0435\u043b\u044c'), (b'ot', '\u0434\u0440\u0443\u0433\u043e\u0435')], default=b'na', max_length=2), + field=models.CharField(choices=[('na', 'не выбрано'), ('yt', 'жёлтый треугольник'), ('rc', 'красный крестик'), ('ls', 'слабая скорость'), ('cf', 'обрыв кабеля'), ('cn', 'подключение'), ('pf', 'переодическое пропадание'), ('cr', 'настройка роутера'), ('co', 'настроить onu'), ('fc', 'обжать кабель'), ('ot', 'другое')], default='na', max_length=2), ), migrations.AlterField( model_name='task', name='priority', - field=models.CharField(choices=[(b'A', '\u0412\u044b\u0441\u0448\u0438\u0439'), (b'C', '\u0421\u0440\u0435\u0434\u043d\u0438\u0439'), (b'E', '\u041d\u0438\u0437\u043a\u0438\u0439')], default=b'E', max_length=1), + field=models.CharField(choices=[('A', 'Высший'), ('C', 'Средний'), ('E', 'Низкий')], default='E', max_length=1), ), ] diff --git a/taskapp/migrations/0007_auto_20161206_2303.py b/taskapp/migrations/0007_auto_20161206_2303.py index 09cd5ce..8a7de3b 100644 --- a/taskapp/migrations/0007_auto_20161206_2303.py +++ b/taskapp/migrations/0007_auto_20161206_2303.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-06 20:03 -from __future__ import unicode_literals from django.db import migrations, models import django.db.models.deletion diff --git a/taskapp/migrations/0008_auto_20161213_1932.py b/taskapp/migrations/0008_auto_20161213_1932.py index 37cd064..3d940e7 100644 --- a/taskapp/migrations/0008_auto_20161213_1932.py +++ b/taskapp/migrations/0008_auto_20161213_1932.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-13 16:32 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models @@ -19,13 +18,13 @@ class Migration(migrations.Migration): name='ChangeLog', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('act_type', models.CharField(choices=[(b'e', '\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'c', '\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'd', '\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438')], max_length=1)), + ('act_type', models.CharField(choices=[('e', 'Изменение задачи'), ('c', 'Создание задачи'), ('d', 'Удаление задачи')], max_length=1)), ('when', models.DateTimeField(auto_now_add=True)), ], ), migrations.AlterModelOptions( name='task', - options={'ordering': ('-id',), 'permissions': (('can_viewall', '\u0414\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u043c'),)}, + options={'ordering': ('-id',), 'permissions': (('can_viewall', 'Доступ ко всем задачам'),)}, ), migrations.AddField( model_name='changelog', diff --git a/taskapp/migrations/0009_auto_20161216_2214.py b/taskapp/migrations/0009_auto_20161216_2214.py index 0e04c25..44e5786 100644 --- a/taskapp/migrations/0009_auto_20161216_2214.py +++ b/taskapp/migrations/0009_auto_20161216_2214.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-16 19:14 -from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models diff --git a/taskapp/migrations/0010_auto.py b/taskapp/migrations/0010_auto.py index fadd689..a7399ac 100644 --- a/taskapp/migrations/0010_auto.py +++ b/taskapp/migrations/0010_auto.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-12-18 16:03 -from __future__ import unicode_literals from django.db import migrations, models @@ -14,11 +13,11 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='task', - options={'ordering': ('-id',), 'permissions': (('can_viewall', '\u0414\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u043c'), ('can_remind', '\u041d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043e \u0437\u0430\u0434\u0430\u0447\u0430\u0445'))}, + options={'ordering': ('-id',), 'permissions': (('can_viewall', 'Доступ ко всем задачам'), ('can_remind', 'Напоминания о задачах'))}, ), migrations.AlterField( model_name='changelog', name='act_type', - field=models.CharField(choices=[(b'e', '\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'c', '\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'd', '\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'f', '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438'), (b'b', '\u0417\u0430\u0434\u0430\u0447\u0430 \u043d\u0430\u0447\u0430\u0442\u0430')], max_length=1), + field=models.CharField(choices=[('e', 'Изменение задачи'), ('c', 'Создание задачи'), ('d', 'Удаление задачи'), ('f', 'Завершение задачи'), ('b', 'Задача начата')], max_length=1), ), ] diff --git a/taskapp/migrations/0011_auto_20170116_0126.py b/taskapp/migrations/0011_auto_20170116_0126.py index 5046522..e3bbdb2 100644 --- a/taskapp/migrations/0011_auto_20170116_0126.py +++ b/taskapp/migrations/0011_auto_20170116_0126.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.9 on 2017-01-15 22:26 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/taskapp/models.py b/taskapp/models.py index 3d18c84..579b8c9 100644 --- a/taskapp/models.py +++ b/taskapp/models.py @@ -1,65 +1,59 @@ # coding=utf-8 -from __future__ import unicode_literals - from datetime import datetime, timedelta -#import os -#from subprocess import call from django.db import models from django.conf import settings from abonapp.models import Abon - -#from devapp.models import Device -#from djing.settings import BASE_DIR -from handle import handle as task_handle +from .handle import handle as task_handle TASK_PRIORITIES = ( - (b'A', u'Высший'), - (b'C', u'Средний'), - (b'E', u'Низкий') + ('A', 'Высший'), + ('C', 'Средний'), + ('E', 'Низкий') ) TASK_STATES = ( - (b'S', u'Новая'), - (b'C', u'На выполнении'), - (b'F', u'Выполнена') + ('S', 'Новая'), + ('C', 'На выполнении'), + ('F', 'Выполнена') ) TASK_TYPES = ( - (b'na', u'не выбрано'), - (b'yt', u'жёлтый треугольник'), - (b'rc', u'красный крестик'), - (b'ls', u'слабая скорость'), - (b'cf', u'обрыв кабеля'), - (b'cn', u'подключение'), - (b'pf', u'переодическое пропадание'), - (b'cr', u'настройка роутера'), - (b'co', u'настроить onu'), - (b'fc', u'обжать кабель'), - (b'ot', u'другое') + ('na', 'не выбрано'), + ('yt', 'жёлтый треугольник'), + ('rc', 'красный крестик'), + ('ls', 'слабая скорость'), + ('cf', 'обрыв кабеля'), + ('cn', 'подключение'), + ('pf', 'переодическое пропадание'), + ('cr', 'настройка роутера'), + ('co', 'настроить onu'), + ('fc', 'обжать кабель'), + ('ot', 'другое') ) class ChangeLog(models.Model): task = models.ForeignKey('Task') ACT_CHOICES = ( - (b'e', u'Изменение задачи'), - (b'c', u'Создание задачи'), - (b'd', u'Удаление задачи'), - (b'f', u'Завершение задачи'), - (b'b', u'Задача начата') + ('e', 'Изменение задачи'), + ('c', 'Создание задачи'), + ('d', 'Удаление задачи'), + ('f', 'Завершение задачи'), + ('b', 'Задача начата') ) act_type = models.CharField(max_length=1, choices=ACT_CHOICES) when = models.DateTimeField(auto_now_add=True) who = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+') - def __unicode__(self): + def __str__(self): return self.get_act_type_display() def _delta_add_days(): return datetime.now() + timedelta(days=3) + class Task(models.Model): descr = models.CharField(max_length=128, null=True, blank=True) recipients = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='them_task') @@ -82,40 +76,39 @@ class Task(models.Model): ) def finish(self, current_user): - self.state = b'F' # Выполнена + self.state = 'F' # Выполнена self.out_date = datetime.now() # Время завершения ChangeLog.objects.create( task=self, - act_type=b'f', + act_type='f', who=current_user ) self.save(update_fields=['state', 'out_date']) def begin(self, current_user): - self.state = b'C' # Начата + self.state = 'C' # Начата ChangeLog.objects.create( task=self, - act_type=b'b', + act_type='b', who=current_user ) self.save(update_fields=['state']) def task_handler(sender, instance, **kwargs): - #cur_dir = os.path.join(BASE_DIR, "taskapp") group = '' if instance.abon: group = instance.abon.group if kwargs['created']: ChangeLog.objects.create( task=instance, - act_type=b'c', + act_type='c', who=instance.author ) else: ChangeLog.objects.create( task=instance, - act_type=b'e', + act_type='e', who=instance.author ) for recipient in instance.recipients.all(): @@ -123,27 +116,12 @@ def task_handler(sender, instance, **kwargs): instance, instance.author, recipient, group ) - ''' - call(['%s/handle.sh' % cur_dir, - first_param, # start or change - instance.get_mode_display(), # mode - Характер поломки - 'N', # (ip устройства) Зарезервировано - instance.state, # Состояние задачи (новая|выполнена) - instance.author.telephone, # Телефон автора задачи - recipient.telephone, # Телефон ответственного монтажника - instance.descr, # Описание задачи - # Если указан абонент то инфа о нём - instance.abon.fio if instance.abon else '<нет фио>', - instance.abon.address if instance.abon else '<нет адреса>', - instance.abon.telephone if instance.abon else '<нет телефона>', - group_name]) # Имя группы абонента - ''' def task_delete(sender, instance, **kwargs): ChangeLog.objects.create( task=instance, - act_type=b'd', + act_type='d', who=instance.author ) diff --git a/taskapp/urls.py b/taskapp/urls.py index 1be4932..e297e3c 100644 --- a/taskapp/urls.py +++ b/taskapp/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from . import views urlpatterns = [ diff --git a/taskapp/views.py b/taskapp/views.py index 45da024..ffd7c81 100644 --- a/taskapp/views.py +++ b/taskapp/views.py @@ -6,9 +6,10 @@ from django.contrib import messages from abonapp.models import Abon from datetime import date from chatbot.models import TelegramBot -from models import Task +from .models import Task from mydefs import pag_mn, only_admins, safe_int -from forms import TaskFrm +from .forms import TaskFrm +from .handle import TaskException @login_required @@ -148,13 +149,13 @@ def task_add_edit(request, task_id=0): task_instance.save() return redirect('taskapp:home') else: - messages.error(request, u'Нет ответственных за группу, в которой находится выбранный абонент') + messages.error(request, 'Нет ответственных за группу, в которой находится выбранный абонент') else: - messages.error(request, u'Нужно выбрать абонента') + messages.error(request, 'Нужно выбрать абонента') else: - messages.error(request, u'Ошибка в полях формы в задаче') + messages.error(request, 'Ошибка в полях формы в задаче') except TelegramBot.DoesNotExist: - messages.error(request, u'Исполнитель ещё не подписался на оповещения') + messages.error(request, 'Исполнитель ещё не подписался на оповещения') return render(request, 'taskapp/add_edit_task.html', { 'form': frm, @@ -166,8 +167,11 @@ def task_add_edit(request, task_id=0): @login_required @only_admins def task_finish(request, task_id): - task = get_object_or_404(Task, id=task_id) - task.finish(request.user) + try: + task = get_object_or_404(Task, id=task_id) + task.finish(request.user) + except TaskException as e: + messages.error(request, e) return redirect('taskapp:home')