Browse Source

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

devel
Dmitry Novikov 8 years ago
parent
commit
ee31263323
  1. 1
      README.md
  2. 8
      devapp/templates/devapp/devices.html
  3. 2
      devapp/urls.py
  4. 53
      devapp/views.py
  5. 30
      djing/global_base_views.py
  6. BIN
      docs/img/pagination.png
  7. 56
      docs/views.md
  8. 1
      mydefs.py
  9. 26
      templates/toolbar_page_cbv.html

1
README.md

@ -10,3 +10,4 @@ P.S. Возможно понадобится **Python 3.5** и выше из-з
* [Установка](./docs/install.md) * [Установка](./docs/install.md)
* [Разработка расширений](./docs/dev.md) * [Разработка расширений](./docs/dev.md)
* [Сбор информации трафика по netflow](./docs/netflow.md) * [Сбор информации трафика по netflow](./docs/netflow.md)
* [Работа с представлениями](./docs/views.md)

8
devapp/templates/devapp/devices.html

@ -17,13 +17,13 @@
<tr> <tr>
<th>#</th> <th>#</th>
<th class="col-md-2"> <th class="col-md-2">
<a href="{% url 'devapp:devs' group.pk %}?order_by=ip_address&dir={{ dir|default:"down" }}">
<a href="{% url 'devapp:devs' group.pk %}?order_by=ip_address&dir={{ dir|default:'down' }}">
{% trans 'Ip address' %} {% trans 'Ip address' %}
</a> </a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th class="col-md-5"> <th class="col-md-5">
<a href="{% url 'devapp:devs' group.pk %}?order_by=comment&dir={{ dir|default:"down" }}">
<a href="{% url 'devapp:devs' group.pk %}?order_by=comment&dir={{ dir|default:'down' }}">
{% trans 'Comment' %} {% trans 'Comment' %}
</a> </a>
{% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -31,7 +31,7 @@
<th class="col-md-3">{% trans 'Mac address' %}</th> <th class="col-md-3">{% trans 'Mac address' %}</th>
{# <th class="col-md-3 hidden-xs hidden-sm">{% trans 'Plugin output' %}</th> #} {# <th class="col-md-3 hidden-xs hidden-sm">{% trans 'Plugin output' %}</th> #}
<th class="col-md-1"> <th class="col-md-1">
<a href="{% url 'devapp:devs' group.pk %}?order_by=devtype&dir={{ dir|default:"down" }}">
<a href="{% url 'devapp:devs' group.pk %}?order_by=devtype&dir={{ dir|default:'down' }}">
{% trans 'Device type' %} {% trans 'Device type' %}
</a> </a>
{% if order_by == 'devtype' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'devtype' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -96,6 +96,6 @@
</table> </table>
</div> </div>
{% include 'toolbar_page.html' with pag=devices %}
{% include 'toolbar_page_cbv.html' %}
{% endblock %} {% endblock %}

2
devapp/urls.py

@ -9,7 +9,7 @@ urlpatterns = [
url(r'^$', views.group_list, name='group_list'), url(r'^$', views.group_list, name='group_list'),
url(r'^devices_without_groups$', views.devices_null_group, name='devices_null_group'), url(r'^devices_without_groups$', views.devices_null_group, name='devices_null_group'),
url(r'^fix_onu/$', views.fix_onu, name='fix_onu'), url(r'^fix_onu/$', views.fix_onu, name='fix_onu'),
url(r'^(?P<group_id>\d+)$', views.devices, name='devs'),
url(r'^(?P<group_id>\d+)$', views.DevicesListView.as_view(), name='devs'),
url(r'^(?P<group_id>\d+)/add$', views.dev, name='add'), url(r'^(?P<group_id>\d+)/add$', views.dev, name='add'),
url(r'^(\d+)/(?P<device_id>\d+)$', views.devview, name='view'), url(r'^(\d+)/(?P<device_id>\d+)$', views.devview, name='view'),
url(r'^(\d+)/(?P<device_id>\d+)/del$', views.devdel, name='del'), url(r'^(\d+)/(?P<device_id>\d+)/del$', views.devdel, name='del'),

53
devapp/views.py

@ -11,6 +11,7 @@ from django.contrib import messages
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _, gettext from django.utils.translation import gettext_lazy as _, gettext
from easysnmp import EasySNMPTimeoutError, EasySNMPError from easysnmp import EasySNMPTimeoutError, EasySNMPError
from django.views.generic import ListView
from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper, ip_addr_regex from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper, ip_addr_regex
from abonapp.models import AbonGroup, Abon from abonapp.models import AbonGroup, Abon
@ -20,38 +21,42 @@ from guardian.shortcuts import get_objects_for_user
from chatbot.telebot import send_notify from chatbot.telebot import send_notify
from chatbot.models import ChatException from chatbot.models import ChatException
from jsonview.decorators import json_view from jsonview.decorators import json_view
from djing.global_base_views import HashAuthView, AllowedSubnetMixin
from djing.global_base_views import HashAuthView, AllowedSubnetMixin, OrderingMixin
from .models import Device, Port, DeviceDBException, DeviceMonitoringException from .models import Device, Port, DeviceDBException, DeviceMonitoringException
from .forms import DeviceForm, PortForm from .forms import DeviceForm, PortForm
from mydefs import safe_int
@login_required
@only_admins
def devices(request, group_id):
group = get_object_or_404(AbonGroup, pk=group_id)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied
try:
devs = Device.objects.filter(user_group=group) \
.select_related('user_group') \
.only('comment', 'mac_addr', 'devtype', 'user_group', 'pk', 'ip_address')
PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
dr, field = order_helper(request)
if field:
devs = devs.order_by(field)
devs = pag_mn(request, devs)
#devs = Device.objects.wrap_monitoring_info(devs)
@method_decorator([login_required, only_admins], name='dispatch')
class DevicesListView(ListView, OrderingMixin):
context_object_name = 'devices'
template_name = 'devapp/devices.html'
paginate_by = PAGINATION_ITEMS_PER_PAGE
http_method_names = ['get']
except (DeviceDBException, DeviceMonitoringException) as e:
messages.error(request, e)
def get_queryset(self):
group_id = safe_int(self.kwargs.get('group_id'))
queryset = Device.objects.filter(user_group__pk=group_id) \
.select_related('user_group') \
.only('comment', 'mac_addr', 'devtype', 'user_group', 'pk', 'ip_address')
return queryset
return render(request, 'devapp/devices.html', {
'devices': devs,
'dir': dr,
'order_by': request.GET.get('order_by'),
'group': group
})
def get_context_data(self, **kwargs):
group_id = safe_int(self.kwargs.get('group_id'))
context = super(DevicesListView, self).get_context_data(**kwargs)
context['group'] = get_object_or_404(AbonGroup, pk=group_id)
return context
def dispatch(self, request, *args, **kwargs):
try:
response = super(DevicesListView, self).dispatch(request, *args, **kwargs)
except (DeviceDBException, DeviceMonitoringException) as e:
messages.error(request, e)
response = HttpResponse('Error')
return response
@login_required @login_required

30
djing/global_base_views.py

@ -58,3 +58,33 @@ class AllowedSubnetMixin(object):
return super(AllowedSubnetMixin, self).dispatch(request, *args, **kwargs) return super(AllowedSubnetMixin, self).dispatch(request, *args, **kwargs)
else: else:
return HttpResponseForbidden('Access Denied') return HttpResponseForbidden('Access Denied')
class OrderingMixin(object):
"""
Ordering result object list by @order_by variable in get request.
For example url?order_by=username orders objects by username.
@dir - direction of ordering. down or up.
@order_by - ordering field name
"""
def get_context_data(self, **kwargs):
context = super(OrderingMixin, self).get_context_data(**kwargs)
context['order_by'] = self.request.GET.get('order_by')
direction = self.request.GET.get('dir')
if direction == 'down':
direction = 'up'
elif direction == 'up':
direction = 'down'
else:
direction = ''
context['dir'] = direction
return context
def get_ordering(self):
direction = self.request.GET.get('dir')
order_by = self.request.GET.get('order_by')
dfx = ''
if direction == 'down':
dfx = '-'
if order_by:
return ["%s%s" % (dfx, order_by)]

BIN
docs/img/pagination.png

After

Width: 223  |  Height: 68  |  Size: 1.3 KiB

56
docs/views.md

@ -0,0 +1,56 @@
# Работа с представлениями
При разработке представлений мне пришлось реализовать несколько алгоритмов, которых
нет в поставке Django. Они связаны с особенностями реализации системы.
* [Пагинатор](#markdown-header-пагинатор)
* [Сортировка по полям объектов из списка](markdown-header-сортировка-по-полям-объектов-из-списка)
### Пагинатор
Есть реализованный шаблон для пагинации. При использовании [Class Based View](https://docs.djangoproject.com/en/1.11/topics/class-based-views/),
в шаблоне вы можете включить страницу *templates/toolbar_page_cbv.html*.
Например вы создали клас представления:
```python
from django.views.generic import ListView
class PaysListView(ListView):
...
pass
```
Тогда в шаблоне с bootstrap вы можете увидеть примерно такую пагинацию которую
вы конечно же можете изменить на свою.
![paginator](./img/pagination.png).
### Сортировка по полям объектов из списка
Для того чтоб иметь возможность сортировать по полю объекта из списка, в шаблоне нужно передать
имя поля по которому нужна сортировка и направление сортировки.
На примере *devapp/devices.html* можно рассмотреть такую сортировку.
Там указан url с параметрами
> {% url 'devapp:devs' group.pk %}?order_by=ip_address&dir={{ dir|default:'down' }}
Тут обратная сортировка по полю *ip_address*, со знаком -. То есть эквивалент будет выглядеть примерно так:
> Device.objects.all().order_by('-ip_address')
После того как вы отсортируете один раз, направление поменяется, в переменную dir будет передано
значение *up*, и сортировка пройдёт без знака -
В то же время ваше представление нужно отнаследовать от OrderingMixin из *djing.global_base_views*.
Определение представления с сортировкой будет выглядеть так:
```python
from django.views.generic import ListView
from djing.global_base_views import OrderingMixin
class PaysListView(ListView, OrderingMixin):
...
pass
```
Примесь *OrderingMixin* добавляет в контекст переменные *order_by* и *dir* для использования в шалоне.

1
mydefs.py

@ -128,6 +128,7 @@ class MyChoicesAdapter(Iterator):
# через get должно быть передано order_by=<поле в бд> а в dir=<up|down> направление сортировки # через get должно быть передано order_by=<поле в бд> а в dir=<up|down> направление сортировки
# возвращает новое направление сортировки и поле для сортировки с направлением # возвращает новое направление сортировки и поле для сортировки с направлением
def order_helper(request): def order_helper(request):
print('DEPRECATION: use global_base_views.OrderingMixin')
dr = request.GET.get('dir') dr = request.GET.get('dir')
dfx = '' dfx = ''
if dr == 'down': if dr == 'down':

26
templates/toolbar_page_cbv.html

@ -0,0 +1,26 @@
{% if paginator.num_pages > 1 %}
{% load dpagination %}
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<ul class="pagination">
{% if page_obj.number == 1 %}
<li class="disabled"><a href="#">&laquo;</a></li>
{% else %}
<li><a href="?{% url_page_replace request 'page' 1 %}">&laquo;</a></li>
{% endif %}
{% if page_obj.has_previous %}
<li><a href="?{% url_page_replace request 'page' page_obj.previous_page_number %}">{{ page_obj.previous_page_number }}</a></li>
{% endif %}
<li class="disabled"><a href="#">{{ page_obj.number }}</a></li>
{% if page_obj.has_next %}
<li><a href="?{% url_page_replace request 'page' page_obj.next_page_number %}">{{ page_obj.next_page_number }}</a></li>
{% endif %}
{% if page_obj.number == paginator.num_pages %}
<li class="disabled"><a href="#">&raquo;</a></li>
{% else %}
<li><a href="?{% url_page_replace request 'page' paginator.num_pages %}">&raquo;</a></li>
{% endif %}
</ul>
</div>
</div>
{% endif %}
Loading…
Cancel
Save