Browse Source

Merge branch 'docs' of https://github.com/nerosketch/djing into devel

devel
bashmak 9 years ago
parent
commit
7baef39810
  1. 4
      abonapp/pay_systems.py
  2. 12
      accounts_app/models.py
  3. 4
      agent/mod_mikrotik.py
  4. 3
      chatbot/locale/ru/LC_MESSAGES/django.po
  5. 4
      chatbot/models.py
  6. 2
      chatbot/telebot.py
  7. 2
      cron.py
  8. 4
      devapp/views.py
  9. 2
      djing/settings_example.py
  10. 0
      docs/ats.md
  11. BIN
      docs/img/login.png
  12. 294
      docs/install.md
  13. 5
      mydefs.py
  14. 3
      photo_app/models.py
  15. 7
      requirements.txt
  16. 3
      setup.py

4
abonapp/pay_systems.py

@ -3,9 +3,11 @@ from django.utils import timezone
from mydefs import safe_int, safe_float from mydefs import safe_int, safe_float
from .models import Abon, AllTimePayLog from .models import Abon, AllTimePayLog
from django.db import DatabaseError from django.db import DatabaseError
from django.conf import settings
from djing.settings import pay_SECRET as SECRET, pay_SERV_ID as SERV_ID
SECRET = getattr(settings, 'pay_SECRET')
SERV_ID = getattr(settings, 'pay_SERV_ID')
#?ACT=1&PAY_ACCOUNT=960849&SERVICE_ID=y832r92y8f9e&PAY_ID=3561234&TRADE_POINT=377&SIGN=32e533a72389fe4e93746509f9d672f8 #?ACT=1&PAY_ACCOUNT=960849&SERVICE_ID=y832r92y8f9e&PAY_ID=3561234&TRADE_POINT=377&SIGN=32e533a72389fe4e93746509f9d672f8

12
accounts_app/models.py

@ -3,11 +3,14 @@ from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from djing.settings import DEFAULT_PICTURE
from django.conf import settings
from photo_app.models import Photo from photo_app.models import Photo
DEFAULT_PICTURE = getattr(settings, 'DEFAULT_PICTURE', '/static/images/default-avatar.png')
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
class MyUserManager(BaseUserManager): class MyUserManager(BaseUserManager):
def create_user(self, telephone, username, password=None): def create_user(self, telephone, username, password=None):
""" """
@ -51,7 +54,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
max_length=16, max_length=16,
verbose_name=_('Telephone'), verbose_name=_('Telephone'),
#unique=True, #unique=True,
validators=[RegexValidator('^\+[7,8,9,3]\d{10,11}$')]
validators=[RegexValidator(TELEPHONE_REGEXP)]
) )
avatar = models.ForeignKey(Photo, null=True, blank=True, on_delete=models.SET_NULL) avatar = models.ForeignKey(Photo, null=True, blank=True, on_delete=models.SET_NULL)
email = models.EmailField(default='admin@example.ru') email = models.EmailField(default='admin@example.ru')
@ -65,13 +68,12 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
def get_short_name(self): def get_short_name(self):
return self.username or self.telephone return self.username or self.telephone
# Use UserManager to get the create_user method, etc. # Use UserManager to get the create_user method, etc.
objects = MyUserManager() objects = MyUserManager()
@property @property
def is_staff(self): def is_staff(self):
"Is the user a member of staff?"
" Is the user a member of staff?"
# Simplest possible answer: All admins are staff # Simplest possible answer: All admins are staff
return self.is_admin return self.is_admin

4
agent/mod_mikrotik.py

@ -7,11 +7,11 @@ from .core import BaseTransmitter, NasFailedResult, NasNetworkError
from mydefs import ping from mydefs import ping
from .structs import TariffStruct, AbonStruct, IpStruct from .structs import TariffStruct, AbonStruct, IpStruct
from . import settings from . import settings
from djing.settings import DEBUG
from django.conf import settings
import re import re
#DEBUG=True
DEBUG = getattr(settings, 'DEBUG', False)
LIST_USERS_ALLOWED = 'DjingUsersAllowed' LIST_USERS_ALLOWED = 'DjingUsersAllowed'
LIST_USERS_BLOCKED = 'DjingUsersBlocked' LIST_USERS_BLOCKED = 'DjingUsersBlocked'

3
chatbot/locale/ru/LC_MESSAGES/django.po

@ -55,3 +55,6 @@ msgstr "Давай пинганём, напиши ip. Нужно будет по
msgid "Yes, it's nice to meet% s, I will notify you about events in billing. Successful work;)" msgid "Yes, it's nice to meet% s, I will notify you about events in billing. Successful work;)"
msgstr "Да, приятно познакомиться %s, я буду оповещать тебя о событиях в биллинге. Удачной работы ;)" msgstr "Да, приятно познакомиться %s, я буду оповещать тебя о событиях в биллинге. Удачной работы ;)"
msgid "Telegram bot token not found"
msgstr "Токен для бота Telegram не найден"

4
chatbot/models.py

@ -1,5 +1,7 @@
from django.db import models from django.db import models
from djing.settings import AUTH_USER_MODEL
from django.conf import settings
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL')
class ChatException(Exception): class ChatException(Exception):

2
chatbot/telebot.py

@ -133,6 +133,8 @@ class DjingTelebot(helper.ChatHandler):
# Просто отправляем текст оповещения указанному админу # Просто отправляем текст оповещения указанному админу
def send_notify(msg_text, account): def send_notify(msg_text, account):
try: try:
if token is None:
raise ChatException(_('Telegram bot token not found'))
tb = TelegramBot.objects.get(user=account) tb = TelegramBot.objects.get(user=account)
tbot = Bot(token) tbot = Bot(token)
tbot.sendMessage(tb.chat_id, msg_text) tbot.sendMessage(tb.chat_id, msg_text)

2
cron.py

@ -15,7 +15,7 @@ def main():
users = Abon.objects.all() users = Abon.objects.all()
for user in users: for user in users:
try: try:
# бдим за услугами абонента: просроченные отключить, заказанные подключить
# бдим за услугами абонента
user.bill_service(user) user.bill_service(user)
# если нет ip то и нет смысла лезть в NAS # если нет ip то и нет смысла лезть в NAS

4
devapp/views.py

@ -14,7 +14,7 @@ from .models import Device, Port, DeviceDBException
from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper
from .forms import DeviceForm, PortForm from .forms import DeviceForm, PortForm
from abonapp.models import AbonGroup, Abon from abonapp.models import AbonGroup, Abon
from djing.settings import DEFAULT_SNMP_PASSWORD
from django.conf import settings
@login_required @login_required
@ -103,7 +103,7 @@ def dev(request, grp, devid=0):
'mac_addr': request.GET.get('mac'), 'mac_addr': request.GET.get('mac'),
'comment': request.GET.get('c'), 'comment': request.GET.get('c'),
'ip_address': request.GET.get('ip'), 'ip_address': request.GET.get('ip'),
'man_passw': DEFAULT_SNMP_PASSWORD
'man_passw': getattr(settings, 'DEFAULT_SNMP_PASSWORD', '')
}) })
else: else:
frm = DeviceForm(instance=devinst) frm = DeviceForm(instance=devinst)

2
djing/settings_example.py

@ -168,3 +168,5 @@ DHCP_TIMEOUT = 14400
DEFAULT_SNMP_PASSWORD = 'public' DEFAULT_SNMP_PASSWORD = 'public'
TELEGRAM_BOT_TOKEN = 'bot token' TELEGRAM_BOT_TOKEN = 'bot token'
TELEPHONE_REGEXP = r'^\+[7,8,9,3]\d{10,11}$'

0
docs/ats.md

BIN
docs/img/login.png

After

Width: 1239  |  Height: 809  |  Size: 14 KiB

294
docs/install.md

@ -2,7 +2,7 @@
Работа предполагается на python3. Работа предполагается на python3.
Я предпочитаю запускать wsgi сервер на связке uWSGI + Nginx, так что ставить будем соответствующие пакеты. Я предпочитаю запускать wsgi сервер на связке uWSGI + Nginx, так что ставить будем соответствующие пакеты.
#####На Fedora25 нужные пакеты можно установить так:
##### На Fedora25 нужные пакеты можно установить так:
Для начала подготовим систему, очистим и обновим пакеты. Процесс обновления долгий, так что можно пойти заварить себе чай :) Для начала подготовим систему, очистим и обновим пакеты. Процесс обновления долгий, так что можно пойти заварить себе чай :)
``` ```
@ -12,13 +12,18 @@
Затем установим зависимости Затем установим зависимости
``` ```
# dnf -y install python3 python3-devel python3-pip python3-pillow mariadb uwsgi nginx redis net-snmp net-snmp-libs net-snmp-utils net-snmp-devel net-snmp-python git redhat-rpm-config
# dnf -y install python3 python3-devel python3-pip python3-pillow mariadb mariadb-devel uwsgi nginx uwsgi-plugin-python3 redis net-snmp net-snmp-libs net-snmp-utils net-snmp-devel net-snmp-python git redhat-rpm-config
```
Лучше чтоб версия python по умолчанию была третья:
```
# ln -sf python3 /usr/bin/python
``` ```
Условимся что путь к папке с проектом находится по адресу: */var/www/djing*. Условимся что путь к папке с проектом находится по адресу: */var/www/djing*.
Дальше создадим каталок для web, затем обновляем pip и ставим проект через pip: Дальше создадим каталок для web, затем обновляем pip и ставим проект через pip:
``` ```
# mkdir /vaw/www
# mkdir /var/www
# cd /var/www # cd /var/www
# pip3 install --upgrade pip # pip3 install --upgrade pip
# git clone https://github.com/nerosketch/djing.git # git clone https://github.com/nerosketch/djing.git
@ -27,91 +32,254 @@
Скопируем конфиги из примеров в реальные: Скопируем конфиги из примеров в реальные:
``` ```
cd /var/www/djing
cp djing/settings_example.py djing/settings.py
cp agent/settings.py.example agent/settings.py
$ cd /var/www/djing
# cp djing/settings_example.py djing/settings.py
# cp agent/settings.py.example agent/settings.py
``` ```
Затем отредактируйте конфиги для своих нужд. Затем отредактируйте конфиги для своих нужд.
Для удобства я создаю пользователя и группу http:http, и всё что связано с web-сервером запускаю от имени http. Для удобства я создаю пользователя и группу http:http, и всё что связано с web-сервером запускаю от имени http.
``` ```
groupadd -r http
useradd -l -M -r -d /dev/null -g http -s /sbin/nologin http
chown -R http:http /var/www
chown -R http:http /etc/nginx
chown -R http:http /etc/uwsgi.*
# groupadd -r http
# useradd -l -M -r -d /dev/null -g http -s /sbin/nologin http
# chown -R http:http /var/www
# chown -R http:http /etc/nginx
# chown -R http:http /etc/uwsgi.*
# chown -R http:http /run/uwsgi/
``` ```
### Настройка WEB Сервера ### Настройка WEB Сервера
Конфиг Nginx на моём рабочем сервере выглядит так: Конфиг Nginx на моём рабочем сервере выглядит так:
```nginx
user http;
worker_processes auto;
pid /run/nginx.pid;
user http;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
upstream djing { server unix:///run/uwsgi/djing.sock; }
server {
listen 80;
server_name <ваш-домен>.com;
root /var/www/djing;
charset utf-8;
# укажите где лежит ваш раздел с медиа для сайта
location /media {
alias /var/www/djing/media;
}
# местоположение статики
location /static {
alias /var/www/djing/static;
}
# тут надо указать путь куда у вас установился Django + путь к статике админки
# путь к Django тут: /usr/lib/python3.5/site-packages/django
# путь к статике соответственно: contrib/admin/static/admin
location /static/admin {
alias /usr/lib/python3.5/site-packages/django/contrib/admin/static/admin;
}
# на корневом url / реагируем с помощью сокета проекта
# у нас он называется "djing": upstream djing { server ...
location / {
uwsgi_pass djing;
include uwsgi_params;
}
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream djing { server unix:///run/uwsgi/djing.sock; }
server {
listen 80;
server_name <ваш-домен>.com;
root /var/www/djing;
charset utf-8;
# укажите где лежит ваш раздел с медиа для сайта
location /media {
alias /var/www/djing/media;
}
# местоположение статики
location /static {
alias /var/www/djing/static;
}
# тут надо указать путь куда у вас установился Django + путь к статике админки
# путь к Django тут: /usr/lib/python3.5/site-packages/django
# путь к статике соответственно: contrib/admin/static/admin
location /static/admin {
alias /usr/lib/python3.5/site-packages/django/contrib/admin/static/admin;
}
# на корневом url / реагируем с помощью сокета проекта
# у нас он называется "djing": upstream djing { server ...
location / {
uwsgi_pass djing;
include uwsgi_params;
} }
} }
}
```
Это минимальный конфиг Nginx для работы. Проверте файл /run/uwsgi/djing.sock на доступность пользователю http для чтения. Это минимальный конфиг Nginx для работы. Проверте файл /run/uwsgi/djing.sock на доступность пользователю http для чтения.
Далее настраиваем uWSGI. Мой конфиг для uWSGI в режиме emperor: Далее настраиваем uWSGI. Мой конфиг для uWSGI в режиме emperor:
> /etc/uwsgi.ini
```ini
[uwsgi]
uid = http
gid = http
pidfile = /run/uwsgi/uwsgi.pid
emperor = /etc/uwsgi.d
stats = /run/uwsgi/stats.sock
chmod-socket = 660
emperor-tyrant = true
cap = setgid,setuid
```
Зададим конфиг для *uwsgi vassal*:
> /etc/uwsgi.d/djing.ini
```ini
[uwsgi]
chdir=/var/www/djing/
module=djing.wsgi
master=True
processes=8
;socket=/run/uwsgi/djing.sock
http-socket=:8000
chmod-socket=664
pidfile=/run/uwsgi/django-master.pid
vacuum=True
plugin=python3
```
Примените к созданному файлу пользователя http:
> \# chown http:http /etc/uwsgi.d/djing.ini
Перед пробой запуска отключим все ограничения фаервола:
> \# systemctl stop firewalld
Или даже отключить, если вы отложите настройку *firewalld* на потом:
> \# systemctl disable firewalld
Перед тем как попробовать запустить тестовый сервер скомпилируйте переводы:
> \$ ./manage.py compilemessages -l ru
Попробуем запустить *uwsgi* и djing без Nginx:
> \# uwsgi --gid http --uid http /etc/uwsgi.d/djing.ini
пробуем зайти в биллинг с браузера на <адрес сервера>:8000. Вам должен показаться диалог входа в систему:
![Login screenshot](./img/login.png)
Для того чтоб uwsgi применял к своим файлам пользователя http, надо подредактировать системный юнит uwsgi, у меня он имеет такой путь:
> /usr/lib/systemd/system/uwsgi.service
В нём надо чтоб chown менял пользователя на http, а не на uwsgi:
> ExecStartPre=/bin/chown -r http:http /run/uwsgi
Теперь, если всё прошло успешно, поменяйте в конфиге */etc/uwsgi.d/djing.ini* сокет с http на unix socket:
Раскомментируйте это:
> socket=/run/uwsgi/djing.sock
И закомментируйте эту строку:
> http-socket=:8000
Строка *http-socket=:8000* была для теста, чтоб посмотреть работает-ли uwsgi сам по себе.
[uwsgi]
uid = http
gid = http
pidfile = /run/uwsgi/uwsgi.pid
emperor = /etc/uwsgi.d
stats = /run/uwsgi/stats.sock
chmod-socket = 660
emperor-tyrant = true
cap = setgid,setuid
Теперь можно попробовать запустить *nginx* и *uwsgi*. Ставим в **djing/settings.py** опцию **DEBUG = False**, и пробуем запустить нужные юниты:
У меня конфиг лежит по адресу /etc/uwsgi.ini
> \# systemctl start uwsgi\
> \# systemctl start nginx
По умолчанию на fedora включено SELinux и вы не сможете зайти на сайт пока не настроите его. Для того, чтоб проверить всё
ли правильно мы настроили, отключите *SELinux* коммандой **setenforce 0* и попробуйте зайти. После успешного запуска вы
можете снова включить опцию и настроить её.
### Настраиваем биллинг
Все настройки биллинга находятся в файле *djing/settings.py*. Большинство опций вы можете найти в документации
[Django settings](https://docs.djangoproject.com/en/1.9/ref/settings).
Те опции, которые были добавлены мной в рамках проекта *djing*, описаны ниже в этом разделе документации по установке.
#### djing/settings.py
**USE_TZ** &mdash; Это опция *Django*, но если вы не работаете в разных часовых диапазонах то я не рекомендую включать
эту опцию чтоб небыло путаницы со временем. Это связано с тем что я ещё не тестировал поведение работы со временем при
включённой опции *USE_TZ*.
**ALLOWED_HOSTS** &mdash; Тоже опция *Django*, но важная для безопасности, укажите в списке возможные имена вашего сервера.
Подробнее в документации [Django settings](https://docs.djangoproject.com/en/1.9/ref/settings/#allowed-hosts).
**DEFAULT_PICTURE** &mdash; Это путь к изображению по умолчанию, оно используется когда нужное изображение не найдено.
**PAGINATION_ITEMS_PER_PAGE** &mdash; Количество выводимых элементов списка на странце с таблицей. Например, если поставить 30,
то на странице абонентов на одной странице будет выведено 30 строк абонентов.
**pay_SERV_ID** &mdash; Эта опция, так же как и **pay_SECRET** опции для платёжной системы *AllTime24*, если вы используете любую
другую платёжную систему то можете удалить эти опции.
**DIALING_MEDIA** &mdash; Путь, где биллинг сможет найти файлы записей asterisk чтоб вывести статистику звонков.
Подробнее читайте в описании работы с [АТС](./ats.ms).
**DHCP_TIMEOUT** &mdash; Время аренды настроек DHCP в секундах.
**DEFAULT_SNMP_PASSWORD** &mdash; Пароль snmp по умолчанию для устройств, чтоб при создании устройства он был заполнен в нужном поле.
Если нет такого пароля то оставьте пустым или None.
**TELEPHONE_REGEXP** &mdash; Регулярное выражение для валидации номера телефона.
#### Создание БД
Подразумевается что сервер баз данных у вас уже есть, или вы его можете установить сами.
В конфиге настроить БД можно по инструкции [Django databases](https://docs.djangoproject.com/en/1.9/ref/settings/#databases).
Убедитесть что вы в папке с проектом, комманда **pwd** должна выдать */var/www/djing*.
Чтоб создать бд, как описано в документации [Django admin \& migrate](https://docs.djangoproject.com/en/1.9/ref/django-admin/#migrate),
нужно запустить **./manage.py migrate** чтоб создать структуру БД. Вывод будет примерно таким:
```
$ ./manage.py migrate
Operations to perform:
Apply all migrations: mapapp, contenttypes, dialing_app, django_messages, taskapp, photo_app, accounts_app, devapp, statistics, tariff_app, admin, sessions, chatbot, auth, abonapp
Running migrations:
Rendering model states... DONE
Applying mapapp.0001_initial... OK
Applying devapp.0001_initial... OK
Applying devapp.0002_auto_20160909_1018... OK
Applying devapp.0003_device_map_dot... OK
Applying photo_app.0001_initial... OK
Applying contenttypes.0001_initial... OK
...
Applying taskapp.0012_auto_20170407_0124... OK
Applying taskapp.0013_auto_20170413_1944... OK
Applying taskapp.0014_auto_20170416_1029... OK
Applying taskapp.0015_auto_20170816_1109... OK
```
После этого вам стоит создать супер пользователя чтоб зайти в систему.
```
$ ./manage.py createsuperuser
```
В интерактивном режиме ответьте на вопросы.
```
$ ./manage.py createsuperuser
Username: username
Telephone: +12223334455
Password:
Password (again):
Superuser created successfully.
```
Обратите внимание на то что номер телефона это обязательное поле для заполнения.
Если у вас не выходит указать номер телефона, то проверте чтоб ваш телефон соответствовал регулярному выражению **^\+[7,8,9,3]\d{10,11}$**.
Если регулярное выражение вам не подхожит, то вы можете изенить его в настройках, см. опции в настройках выше.
После изменения настроек они не сразу вступят в силу, нужно перезагрузить код django, для этого перезапустите **uwsgi**:
> \# systemctl restart uwsgi
Теперь произведите тестовый запуск:
> \# ./manage.py runserver 192.168.0.100:8000
Если не подтягивается статика то проверте чтоб опция **DEBUG** в настройках была **True**.
При условии что адрес вашего сервера *192.168.0.100*, вы сможете открыть биллинг по адресу **http://192.168.0.100:8000/**.
Введите логин и пароль супер пользователя которого вы создали по инструкции выше.
Если вы успешно зашли то можно пробовать запускать биллинг в рабочую обстановку.
В настройках смените переменную **DEBUG** на **False** и перезапустите *uwsgi*.
### Настраиваем демоны ### Настраиваем демоны
Если ваша система работает с поддержкой *systemd* то в каталоге *systemd_units* проекта вы найдёте юниты для systemd.
Если ваша система работает с поддержкой [**systemd**](https://www.freedesktop.org/wiki/Software/systemd/) то в каталоге *systemd_units* проекта вы найдёте юниты для systemd.
Скопируйте их в каталог юнитов systemd, у меня это путь */etc/systemd/system*. Скопируйте их в каталог юнитов systemd, у меня это путь */etc/systemd/system*.
__Настоятельно рекомендую заглянуть внутрь этих юнитов__. Проверте пути исполняемых файлов, права и прочее. __Настоятельно рекомендую заглянуть внутрь этих юнитов__. Проверте пути исполняемых файлов, права и прочее.
Для запуска сервиса **djing_rotate.service** вам нужно сначала настроить сбор статистики по [netflow](./netflow.md).
Перед включением юнита *djing_telebot.service* создайте Telegram бота и впишите в файл *djing/settings.py* в переменную *TELEGRAM_BOT_TOKEN* токен вашего бота.
С помощью этого бота вы будете получать различные сообщения из биллинга. Подробнее в инструкции к [модулю оповещений](./bot.md).
А теперь включим и запустим нужные демоны А теперь включим и запустим нужные демоны
```
```shell
# systemctl daemon-reload # systemctl daemon-reload
# systemctl enable djing_queue.service # systemctl enable djing_queue.service
# systemctl start djing_queue.service # systemctl start djing_queue.service
@ -120,5 +288,3 @@ __Настоятельно рекомендую заглянуть внутрь
# systemctl enable djing_telebot.service # systemctl enable djing_telebot.service
# systemctl start djing_telebot.service # systemctl start djing_telebot.service
``` ```
Перед включением юнита *djing_telebot.service* создайте Telegram бота и впишите в файл *djing/settings.py* в переменную *TELEGRAM_BOT_TOKEN* токен вашего бота.
С помощью этого бота вы будете получать различные сообщения из биллинга. Подробнее в инструкции к [модулю оповещений](./docs/bot.md).

5
mydefs.py

@ -10,9 +10,12 @@ from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import redirect from django.shortcuts import redirect
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db import models from django.db import models
from djing.settings import PAGINATION_ITEMS_PER_PAGE, DEBUG
from django.conf import settings
PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
DEBUG = getattr(settings, 'DEBUG', False)
ip_addr_regex = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' ip_addr_regex = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'

3
photo_app/models.py

@ -5,8 +5,9 @@ import hashlib
from django.db import models from django.db import models
from PIL import Image from PIL import Image
from django.conf import settings
from djing.settings import BASE_DIR
BASE_DIR = getattr(settings, 'BASE_DIR', '.')
class Photo(models.Model): class Photo(models.Model):

7
requirements.txt

@ -1,11 +1,16 @@
Django==1.9 Django==1.9
Pillow Pillow
telepot telepot
# for mac address field # for mac address field
netaddr netaddr
# for testing required xmltodict # for testing required xmltodict
xmltodict xmltodict
PyMySQL
# Django recommended mysql client
mysqlclient
easysnmp easysnmp
rq rq
pid pid

3
setup.py

@ -1,3 +0,0 @@
#!/usr/bin/env python3
import os
import sys
Loading…
Cancel
Save