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/dev.md)
* [Сбор информации трафика по netflow](./docs/netflow.md)
* [Работа с представлениями](./docs/views.md)

8
devapp/templates/devapp/devices.html

@ -17,13 +17,13 @@
<tr>
<th>#</th>
<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' %}
</a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<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' %}
</a>
{% 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 hidden-xs hidden-sm">{% trans 'Plugin output' %}</th> #}
<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' %}
</a>
{% if order_by == 'devtype' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -96,6 +96,6 @@
</table>
</div>
{% include 'toolbar_page.html' with pag=devices %}
{% include 'toolbar_page_cbv.html' %}
{% endblock %}

2
devapp/urls.py

@ -9,7 +9,7 @@ urlpatterns = [
url(r'^$', views.group_list, name='group_list'),
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'^(?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'^(\d+)/(?P<device_id>\d+)$', views.devview, name='view'),
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.translation import gettext_lazy as _, gettext
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 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.models import ChatException
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 .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

30
djing/global_base_views.py

@ -58,3 +58,33 @@ class AllowedSubnetMixin(object):
return super(AllowedSubnetMixin, self).dispatch(request, *args, **kwargs)
else:
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> направление сортировки
# возвращает новое направление сортировки и поле для сортировки с направлением
def order_helper(request):
print('DEPRECATION: use global_base_views.OrderingMixin')
dr = request.GET.get('dir')
dfx = ''
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