Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created angular-free version of committees page #100

Merged
merged 5 commits into from
Sep 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions dienst2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@
'django.template.loaders.app_directories.Loader',
)

TEMPLATES = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waar is dit voor nodig?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

om 1 of andere reden kon ik in de templates niet request.META benaderen ofzo, dus toen heb ik dit toegevoegd.

Als je vraagt waarom het tegenwoordig in een TEMPLATES variable zit, dat is omdat je makkelijker je template renderer kan wisselen sinds django 1.8, dus je kan ook per template backend andere settings hebben.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright :)

{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
]
}
},
]

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
Expand Down
152 changes: 152 additions & 0 deletions dienst2/templatetags/query_string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# As found on https://djangosnippets.org/snippets/2413/
import re
from django.template import Library, Node, TemplateSyntaxError
from django.http import QueryDict
from django.utils.encoding import smart_str

register = Library()

@register.tag
def query_string(parser, token):
"""
Template tag for creating and modifying query strings.

Syntax:
{% query_string [<base_querystring>] [modifier]* [as <var_name>] %}

modifier is <name><op><value> where op in {=, +, -}

Parameters:
- base_querystring: literal query string, e.g. '?tag=python&tag=django&year=2011',
or context variable bound to either
- a literal query string,
- a python dict with potentially lists as values, or
- a django QueryDict object
May be '' or None or missing altogether.
- modifiers may be repeated and have the form <name><op><value>.
They are processed in the order they appear.
name is taken as is for a parameter name.
op is one of {=, +, -}.
= replace all existing values of name with value(s)
+ add value(s) to existing values for name
- remove value(s) from existing values if present
value is either a literal parameter value
or a context variable. If it is a context variable
it may also be bound to a list.
- as <var name>: bind result to context variable instead of injecting in output
(same as in url tag).

Examples:
1. {% query_string '?tag=a&m=1&m=3&tag=b' tag+'c' m=2 tag-'b' as myqs %}

Result: myqs == '?m=2&tag=a&tag=c'

2. context = {'qs': {'tag': ['a', 'b'], 'year': 2011, 'month': 2},
'tags': ['c', 'd'],
'm': 4,}

{% query_string qs tag+tags month=m %}

Result: '?tag=a&tag=b&tag=c&tag=d&year=2011&month=4
"""
# matches 'tagname1+val1' or 'tagname1=val1' but not 'anyoldvalue'
mod_re = re.compile(r"^(\w+)(=|\+|-)(.*)$")
bits = token.split_contents()
qdict = None
mods = []
asvar = None
bits = bits[1:]
if len(bits) >= 2 and bits[-2] == 'as':
asvar = bits[-1]
bits = bits[:-2]
if len(bits) >= 1:
first = bits[0]
if not mod_re.match(first):
qdict = parser.compile_filter(first)
bits = bits[1:]
for bit in bits:
match = mod_re.match(bit)
if not match:
raise TemplateSyntaxError("Malformed arguments to query_string tag")
name, op, value = match.groups()
mods.append((name, op, parser.compile_filter(value)))
return QueryStringNode(qdict, mods, asvar)

class QueryStringNode(Node):
def __init__(self, qdict, mods, asvar):
self.qdict = qdict
self.mods = mods
self.asvar = asvar
def render(self, context):
mods = [(smart_str(k, 'ascii'), op, v.resolve(context))
for k, op, v in self.mods]
if self.qdict:
qdict = self.qdict.resolve(context)
else:
qdict = None
# Internally work only with QueryDict
qdict = self._get_initial_query_dict(qdict)
#assert isinstance(qdict, QueryDict)
for k, op, v in mods:
qdict.setlist(k, self._process_list(qdict.getlist(k), op, v))
qstring = qdict.urlencode()
if qstring:
qstring = '?' + qstring
if self.asvar:
context[self.asvar] = qstring
return ''
else:
return qstring
def _get_initial_query_dict(self, qdict):
if not qdict:
qdict = QueryDict(None, mutable=True)
elif isinstance(qdict, QueryDict):
qdict = qdict.copy()
elif isinstance(qdict, basestring):
if qdict.startswith('?'):
qdict = qdict[1:]
qdict = QueryDict(qdict, mutable=True)
else:
# Accept any old dict or list of pairs.
try:
pairs = qdict.items()
except:
pairs = qdict
qdict = QueryDict(None, mutable=True)
# Enter each pair into QueryDict object:
try:
for k, v in pairs:
# Convert values to unicode so that detecting
# membership works for numbers.
if isinstance(v, (list, tuple)):
for e in v:
qdict.appendlist(k,unicode(e))
else:
qdict.appendlist(k, unicode(v))
except:
# Wrong data structure, qdict remains empty.
pass
return qdict
def _process_list(self, current_list, op, val):
if not val:
if op == '=':
return []
else:
return current_list
# Deal with lists only.
if not isinstance(val, (list, tuple)):
val = [val]
val = [unicode(v) for v in val]
# Remove
if op == '-':
for v in val:
while v in current_list:
current_list.remove(v)
# Replace
elif op == '=':
current_list = val
# Add
elif op == '+':
for v in val:
current_list.append(v)
return current_list
9 changes: 9 additions & 0 deletions ldb/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import django_filters
from ldb.models import CommitteeMembership


class CommitteeMembershipFilter(django_filters.FilterSet):

class Meta:
model = CommitteeMembership
fields = ('board', 'committee')
2 changes: 1 addition & 1 deletion ldb/templates/ldb/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<li><a href="{% url 'ldb_index' %}">Zoeken</a></li>
<li><a href="{% url 'ldb_people_create' %}">Persoon toevoegen</a></li>
<li><a href="{% url 'ldb_organizations_create' %}">Organisatie toevoegen</a></li>
<li><a href="{% url 'ldb_index_angular' %}#/committees">Commissies</a></li>
<li><a href="{% url 'ldb_committees' %}">Commissies</a></li>
<li><a href="{% url 'ldb_index_angular' %}#/export">Exporteren</a></li>
{% if user.is_staff %}
<li><a href="{% url 'admin:ldb_person_changelist' %}">Beheer</a></li>{% endif %}
Expand Down
75 changes: 75 additions & 0 deletions ldb/templates/ldb/committeemembership_filter.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{% extends 'ldb/base.html' %}
{% load i18n static bootstrap3 query_string %}

{% block title %}{% trans 'Committees' %}{% endblock %}

{% block content %}
<h2 class="page-header">{% trans 'Committees' %}</h2>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans 'Filter' %}
</h3>
</div>
<div class="panel-body">
<form class="form-inline">
{% bootstrap_form filter.form layout='inline' %}
<button type="submit" class="btn btn-primary"><i class="fa fa-filter"></i> Filter</button>
</form>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans 'Search results' %} <span class="badge">{{ filter.count }}</span>
</h3>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>{% trans "Board" %}</th>
<th>{% trans "Committee" %}</th>
<th>{% trans "Name" %}</th>
<th>{% trans "Position" %}</th>
<th>{% trans "RAS" %}</th>
</tr>
</thead>
<tbody>
{% for obj in object_list %}
<tr>
<td>{{ obj.board }}</td>
<td>{{ obj.committee }}</td>
<td><a href="{{ obj.person.get_absolute_url }}">{{ obj.person }}</a></td>
<td>{{ obj.position }}</td>
<td>{{ obj.ras_months }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">{% trans "No people found." %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

{% if is_paginated %}
<nav>
<ul class="pager">
<li{% if not page_obj.has_previous %} class="disabled"{% endif %}>
<a {% if page_obj.has_previous %}
href="{% query_string request.META.QUERY_STRING page=page_obj.previous_page_number %}"{% endif %}>
<span aria-hidden="true">&larr;</span> {% trans "Previous" %}
</a>
</li>
<li{% if not page_obj.has_next %} class="disabled"{% endif %}>
<a {% if page_obj.has_next %}
href="{% query_string request.META.QUERY_STRING page=page_obj.next_page_number %}"{% endif %}>
{% trans "Next" %} <span aria-hidden="true">&rarr;</span>
</a>
</li>
</ul>
</nav>
{% endif %}
{% endblock %}
4 changes: 2 additions & 2 deletions ldb/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from ldb.api import *
from ldb.export import ExportResource
from ldb.views import PersonDetailView, PersonDeleteView, OrganizationDetailView, OrganizationDeleteView, \
index_old, PersonEditView, OrganizationEditView, ResultsView
index_old, PersonEditView, OrganizationEditView, ResultsView, CommitteeMembershipFilterView

api = Api(api_name='v2')

Expand Down Expand Up @@ -49,5 +49,5 @@
name='ldb_organizations_delete'),
url(r'^organizations/(?P<pk>\d+)/edit/$', OrganizationEditView.as_view()),
url(r'^organizations/create/$', OrganizationEditView.as_view(), name='ldb_organizations_create'),

url(r'^committees/$', CommitteeMembershipFilterView.as_view(), name='ldb_committees'),
)
18 changes: 18 additions & 0 deletions ldb/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
from django.template import RequestContext
from django.views.generic import DetailView, DeleteView, TemplateView, UpdateView
from django.views.generic.detail import SingleObjectMixin
from django_filters.views import FilterView
from haystack.inputs import Raw
from haystack.query import SearchQuerySet
from haystack.query import SQ

from dienst2.extras import convert_free_search
from ldb.filters import CommitteeMembershipFilter
from ldb.forms import PersonForm, MemberFormSet, StudentFormSet, AlumnusFormSet, EmployeeFormSet, \
CommitteeMembershipFormSet
from ldb.models import Organization, Person, CommitteeMembership
Expand Down Expand Up @@ -188,3 +190,19 @@ def get_object(self, **kwargs):
return super(PersonEditView, self).get_object(**kwargs)
except AttributeError:
return None


class CommitteeMembershipFilterView(FilterView):
filterset_class = CommitteeMembershipFilter
paginate_by = 50

def get(self, request, *args, **kwargs):
filterset_class = self.get_filterset_class()
self.filterset = self.get_filterset(filterset_class)
self.object_list = self.filterset.qs\
.select_related('person')\
.prefetch_related('committee')\
.order_by('board', 'committee__name', 'person__firstname')
context = self.get_context_data(filter=self.filterset,
object_list=self.object_list)
return self.render_to_response(context)