From e5dad7d7731e2a280f78fb43c50e1b61f8e0244e Mon Sep 17 00:00:00 2001 From: Nicolas Joyard <joyard.nicolas@gmail.com> Date: Mon, 6 Jun 2016 08:13:25 +0200 Subject: [PATCH] Integrate views removed from django-representatives[-votes] --- memopol/api.py | 24 +++--- memopol/templatetags/memopol_tags.py | 37 +++++++- .../content | 10 +-- .../content | 10 +-- .../content | 10 +-- .../content | 10 +-- .../content | 10 +-- memopol/tests/test_representatives_list.py | 21 +++++ memopol/urls.py | 62 +++++++++---- memopol/views/__init__.py | 0 memopol/views/dossier_ac.py | 34 ++++++++ memopol/views/dossier_detail.py | 10 +++ memopol/views/dossier_list.py | 18 ++++ memopol/views/group_list.py | 23 +++++ .../representative_detail.py} | 64 +++++--------- memopol/views/representative_list.py | 86 +++++++++++++++++++ memopol/views/representative_mixin.py | 59 +++++++++++++ .../tests/test_functional.py | 3 +- representatives_positions/views.py | 6 +- templates/_header.haml | 14 +-- templates/home.haml | 2 +- .../_representative_block.haml | 6 +- templates/representatives/group_list.haml | 8 +- .../representative_detail.haml | 5 +- .../representatives/representative_grid.haml | 11 +-- .../representatives/representative_list.haml | 11 +-- .../representatives_votes/dossier_list.haml | 2 +- 27 files changed, 431 insertions(+), 125 deletions(-) create mode 100644 memopol/views/__init__.py create mode 100644 memopol/views/dossier_ac.py create mode 100644 memopol/views/dossier_detail.py create mode 100644 memopol/views/dossier_list.py create mode 100644 memopol/views/group_list.py rename memopol/{views.py => views/representative_detail.py} (50%) create mode 100644 memopol/views/representative_list.py create mode 100644 memopol/views/representative_mixin.py diff --git a/memopol/api.py b/memopol/api.py index 40ae7fc6..cf4c0702 100644 --- a/memopol/api.py +++ b/memopol/api.py @@ -23,14 +23,16 @@ from representatives_recommendations.api import ( router = routers.DefaultRouter() -router.register(r'constituencies', ConstituencyViewSet) -router.register(r'dossiers', DossierViewSet) -router.register(r'dossier_scores', DossierScoreViewSet) -router.register(r'groups', GroupViewSet) -router.register(r'mandates', MandateViewSet) -router.register(r'proposals', ProposalViewSet) -router.register(r'recommendations', RecommendationViewSet) -router.register(r'representatives', RepresentativeViewSet) -router.register(r'scores', RepresentativeScoreViewSet) -router.register(r'vote_scores', VoteScoreViewSet) -router.register(r'votes', VoteViewSet) +router.register(r'constituencies', ConstituencyViewSet, 'api-constituency') +router.register(r'dossiers', DossierViewSet, 'api-dossier') +router.register(r'dossier_scores', DossierScoreViewSet, 'api-dossierscore') +router.register(r'groups', GroupViewSet, 'api-group') +router.register(r'mandates', MandateViewSet, 'api-mandate') +router.register(r'proposals', ProposalViewSet, 'api-proposal') +router.register(r'recommendations', RecommendationViewSet, + 'api-recommendation') +router.register(r'representatives', RepresentativeViewSet, + 'api-representative') +router.register(r'scores', RepresentativeScoreViewSet, 'api-score') +router.register(r'vote_scores', VoteScoreViewSet, 'api-votescore') +router.register(r'votes', VoteViewSet, 'api-vote') diff --git a/memopol/templatetags/memopol_tags.py b/memopol/templatetags/memopol_tags.py index 6c26fea6..840124ba 100644 --- a/memopol/templatetags/memopol_tags.py +++ b/memopol/templatetags/memopol_tags.py @@ -1,7 +1,11 @@ # coding: utf-8 + +import re + from django import template +from django.core.urlresolvers import reverse from django.utils.safestring import mark_safe -import re +from django.utils.html import escape register = template.Library() link = '<a class="{network}-link" href="{url}" target="_blank">{label}</a>' @@ -30,3 +34,34 @@ def website_link(url): def email_link(address): return mark_safe(link.format(network='email', url='mailto:%s' % address, label=address)) + + +@register.simple_tag +def group_url(group): + if group.kind == 'chamber' or group.chamber is None: + return escape(reverse('representative-list', kwargs={ + 'group_kind': group.kind, + 'group': group.name + })) + else: + return escape(reverse('representative-list', kwargs={ + 'group_kind': group.kind, + 'chamber': group.chamber.name, + 'group': group.name + })) + + +@register.simple_tag +def chamber_url(chamber): + return escape(reverse('representative-list', kwargs={ + 'group_kind': 'chamber', + 'group': chamber.name + })) + + +@register.simple_tag +def country_url(country): + return escape(reverse('representative-list', kwargs={ + 'group_kind': 'country', + 'group': country.name + })) diff --git a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist/content b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist/content index 3506bfbb..f2b7e7dd 100644 --- a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist/content +++ b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist/content @@ -43,27 +43,27 @@ </a> </li> <li> - <a href='/legislature/groups/country/'> + <a href='/legislature/group/country/'> Countries </a> </li> <li> - <a href='/legislature/groups/chamber/'> + <a href='/legislature/group/chamber/'> Chambers </a> </li> <li> - <a href='/legislature/groups/group/'> + <a href='/legislature/group/group/'> Parties </a> </li> <li> - <a href='/legislature/groups/delegation/'> + <a href='/legislature/group/delegation/'> Delegations </a> </li> <li> - <a href='/legislature/groups/committee/'> + <a href='/legislature/group/committee/'> Committees </a> </li> diff --git a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist_searchjoly/content b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist_searchjoly/content index 9daa5bb9..9348085d 100644 --- a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist_searchjoly/content +++ b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby12_displaylist_searchjoly/content @@ -43,27 +43,27 @@ </a> </li> <li> - <a href='/legislature/groups/country/'> + <a href='/legislature/group/country/'> Countries </a> </li> <li> - <a href='/legislature/groups/chamber/'> + <a href='/legislature/group/chamber/'> Chambers </a> </li> <li> - <a href='/legislature/groups/group/'> + <a href='/legislature/group/group/'> Parties </a> </li> <li> - <a href='/legislature/groups/delegation/'> + <a href='/legislature/group/delegation/'> Delegations </a> </li> <li> - <a href='/legislature/groups/committee/'> + <a href='/legislature/group/committee/'> Committees </a> </li> diff --git a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby24_displaygrid/content b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby24_displaygrid/content index e9bc5161..9e22cc9f 100644 --- a/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby24_displaygrid/content +++ b/memopol/tests/response_fixtures/RepresentativeListTest.test_page1_paginateby24_displaygrid/content @@ -43,27 +43,27 @@ </a> </li> <li> - <a href='/legislature/groups/country/'> + <a href='/legislature/group/country/'> Countries </a> </li> <li> - <a href='/legislature/groups/chamber/'> + <a href='/legislature/group/chamber/'> Chambers </a> </li> <li> - <a href='/legislature/groups/group/'> + <a href='/legislature/group/group/'> Parties </a> </li> <li> - <a href='/legislature/groups/delegation/'> + <a href='/legislature/group/delegation/'> Delegations </a> </li> <li> - <a href='/legislature/groups/committee/'> + <a href='/legislature/group/committee/'> Committees </a> </li> diff --git a/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby12_displaylist/content b/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby12_displaylist/content index 211f4a3c..e9f36f93 100644 --- a/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby12_displaylist/content +++ b/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby12_displaylist/content @@ -43,27 +43,27 @@ </a> </li> <li> - <a href='/legislature/groups/country/'> + <a href='/legislature/group/country/'> Countries </a> </li> <li> - <a href='/legislature/groups/chamber/'> + <a href='/legislature/group/chamber/'> Chambers </a> </li> <li> - <a href='/legislature/groups/group/'> + <a href='/legislature/group/group/'> Parties </a> </li> <li> - <a href='/legislature/groups/delegation/'> + <a href='/legislature/group/delegation/'> Delegations </a> </li> <li> - <a href='/legislature/groups/committee/'> + <a href='/legislature/group/committee/'> Committees </a> </li> diff --git a/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby24_displaylist/content b/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby24_displaylist/content index 303c9580..9de3976c 100644 --- a/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby24_displaylist/content +++ b/memopol/tests/response_fixtures/RepresentativeListTest.test_page2_paginateby24_displaylist/content @@ -43,27 +43,27 @@ </a> </li> <li> - <a href='/legislature/groups/country/'> + <a href='/legislature/group/country/'> Countries </a> </li> <li> - <a href='/legislature/groups/chamber/'> + <a href='/legislature/group/chamber/'> Chambers </a> </li> <li> - <a href='/legislature/groups/group/'> + <a href='/legislature/group/group/'> Parties </a> </li> <li> - <a href='/legislature/groups/delegation/'> + <a href='/legislature/group/delegation/'> Delegations </a> </li> <li> - <a href='/legislature/groups/committee/'> + <a href='/legislature/group/committee/'> Committees </a> </li> diff --git a/memopol/tests/test_representatives_list.py b/memopol/tests/test_representatives_list.py index f4f3cbb9..04f28f38 100644 --- a/memopol/tests/test_representatives_list.py +++ b/memopol/tests/test_representatives_list.py @@ -1,15 +1,36 @@ # -*- coding: utf8 -*- + from django.test import TestCase from responsediff.response import Response + from .base import UrlGetTestMixin +from representatives.models import Representative +from ..views.representative_mixin import RepresentativeViewMixin class RepresentativeListTest(UrlGetTestMixin, TestCase): fixtures = ['smaller_sample.json'] url = '/legislature/representative/' + def test_prefetch_profile(self): + test = RepresentativeViewMixin() + reps = test.prefetch_for_representative_country_and_main_mandate( + Representative.objects.order_by('pk')) + + with self.assertNumQueries(2): + # Cast to list to avoid [index] to cast a select with an offset + # below ! + reps = [test.add_representative_country_and_main_mandate(r) + for r in reps] + + assert reps[0].country.code == 'GB' + assert reps[0].main_mandate.pk == 3318 + + assert reps[1].country.code == 'FI' + assert reps[1].main_mandate.pk == 5545 + def functional_test(self, page, paginate_by, display, search=''): url = '%s?page=%s&search=%s' % (self.url, page, search) diff --git a/memopol/urls.py b/memopol/urls.py index 1f5931bc..6175d54b 100644 --- a/memopol/urls.py +++ b/memopol/urls.py @@ -3,7 +3,13 @@ from django.conf.urls import include, url from django.contrib import admin from django.views import generic -import views +from views.dossier_ac import DossierAutocomplete, ProposalAutocomplete +from views.dossier_detail import DossierDetail +from views.dossier_list import DossierList +from views.group_list import GroupList +from views.representative_detail import RepresentativeDetail +from views.representative_list import RepresentativeList + import api admin.autodiscover() @@ -11,32 +17,58 @@ admin.autodiscover() urlpatterns = [ # Project-specific overrides url( - r'^legislature/representative/(?P<group_kind>\w+)/(?P<chamber>.+)/' + + r'^legislature/representatives?/(?P<group_kind>\w+)/(?P<chamber>.+)/' + r'(?P<group>.+)/$', - views.RepresentativeList.as_view(), + RepresentativeList.as_view(), + name='representative-list' + ), + url( + r'^legislature/representatives?/(?P<group_kind>\w+)/(?P<group>.+)/$', + RepresentativeList.as_view(), + name='representative-list' + ), + url( + r'^legislature/representatives?/(?P<slug>[-\w]+)/$', + RepresentativeDetail.as_view(), + name='representative-detail' + ), + url( + r'^legislature/groups?/$', + GroupList.as_view(), + name='group-list' + ), + url( + r'^legislature/groups?/(?P<kind>\w+)/$', + GroupList.as_view(), + name='group-list' + ), + url( + r'^legislature/representatives?/$', + RepresentativeList.as_view(), + name='representative-list' ), url( - r'^legislature/representative/(?P<group_kind>\w+)/(?P<group>.+)/$', - views.RepresentativeList.as_view(), + r'^votes/dossiers?/$', + DossierList.as_view(), + name='dossier-list' ), url( - r'^legislature/representative/(?P<slug>[-\w]+)/$', - views.RepresentativeDetail.as_view(), + r'^votes/dossiers?/(?P<pk>\d+)/$', + DossierDetail.as_view(), + name='dossier-detail' ), url( - r'^legislature/representative/$', - views.RepresentativeList.as_view(), + r'^votes/autocomplete/dossier/$', + DossierAutocomplete.as_view(), + name='dossier-autocomplete', ), url( - r'^votes/dossier/$', - views.DossierList.as_view(), + r'^votes/autocomplete/proposal/$', + ProposalAutocomplete.as_view(), + name='proposal-autocomplete', ), url(r'^admin/', include(admin.site.urls)), - url(r'^legislature/', include('representatives.urls', - namespace='representatives')), - url(r'^votes/', include('representatives_votes.urls', - namespace='representatives_votes')), url(r'^positions/', include('representatives_positions.urls', namespace='representatives_positions')), url(r'^api/', include(api.router.urls)), diff --git a/memopol/views/__init__.py b/memopol/views/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/memopol/views/dossier_ac.py b/memopol/views/dossier_ac.py new file mode 100644 index 00000000..03c8525b --- /dev/null +++ b/memopol/views/dossier_ac.py @@ -0,0 +1,34 @@ +# coding: utf-8 + +from dal import autocomplete + +from django.db.models import Q + +from representatives_votes.models import Dossier, Proposal + + +class DossierAutocomplete(autocomplete.Select2QuerySetView): + def get_queryset(self): + qs = Dossier.objects.all() + + if self.q: + qs = qs.filter( + Q(title__icontains=self.q) | + Q(reference__icontains=self.q) + ) + + return qs + + +class ProposalAutocomplete(autocomplete.Select2QuerySetView): + def get_queryset(self): + qs = Proposal.objects.all() + + if self.q: + qs = qs.filter( + Q(dossier__title__icontains=self.q) | + Q(title__icontains=self.q) | + Q(reference__icontains=self.q) + ) + + return qs diff --git a/memopol/views/dossier_detail.py b/memopol/views/dossier_detail.py new file mode 100644 index 00000000..64f43195 --- /dev/null +++ b/memopol/views/dossier_detail.py @@ -0,0 +1,10 @@ +# coding: utf-8 + +from django.views import generic + +from representatives_votes.models import Dossier + + +class DossierDetail(generic.DetailView): + + model = Dossier diff --git a/memopol/views/dossier_list.py b/memopol/views/dossier_list.py new file mode 100644 index 00000000..63335b99 --- /dev/null +++ b/memopol/views/dossier_list.py @@ -0,0 +1,18 @@ +# coding: utf-8 + +from core.views import PaginationMixin + +from django.db.models import Count +from django.views import generic + +from representatives_votes.models import Dossier + + +class DossierList(PaginationMixin, generic.ListView): + + queryset = Dossier.objects.prefetch_related( + 'proposals', + 'proposals__recommendation' + ).annotate( + nb_recomm=Count('proposals__recommendation') + ).order_by('-nb_recomm', '-reference') diff --git a/memopol/views/group_list.py b/memopol/views/group_list.py new file mode 100644 index 00000000..eb500f71 --- /dev/null +++ b/memopol/views/group_list.py @@ -0,0 +1,23 @@ +# coding: utf-8 + +import datetime + +from django.db import models +from django.views import generic + +from representatives.models import Group + + +class GroupList(generic.ListView): + + def get_queryset(self): + qs = Group.objects.filter( + models.Q(mandates__end_date__gte=datetime.date.today()) | + models.Q(mandates__end_date__isnull=True) + ) + + kind = self.kwargs.get('kind', None) + if kind: + qs = qs.filter(kind=kind).distinct() + + return qs.select_related('chamber').order_by('chamber__name', 'name') diff --git a/memopol/views.py b/memopol/views/representative_detail.py similarity index 50% rename from memopol/views.py rename to memopol/views/representative_detail.py index a3f1e8da..7b484e34 100644 --- a/memopol/views.py +++ b/memopol/views/representative_detail.py @@ -1,49 +1,27 @@ -# Project specific "glue" coupling of all apps +# coding: utf-8 + from django.db import models -from django.db.models import Count +from django.views import generic -from core.views import GridListMixin, PaginationMixin, CSVDownloadMixin -from representatives import views as representatives_views -from representatives.models import (Representative, Address, Phone, WebSite) -from representatives_votes import views as representatives_votes_views -from representatives_votes.models import Dossier, Proposal +from representatives.models import Representative, Address, Phone, WebSite from representatives_positions.forms import PositionForm from representatives_recommendations.models import VoteScore +from representatives_votes.models import Proposal +from .representative_mixin import RepresentativeViewMixin -class RepresentativeList( - CSVDownloadMixin, - GridListMixin, - PaginationMixin, - representatives_views.RepresentativeList -): - - csv_name = 'meps.csv' - - def get_csv_results(self, context, **kwargs): - qs = super(RepresentativeList, self).get_queryset() - qs = qs.prefetch_related('email_set') - return [self.add_representative_country_and_main_mandate(r) - for r in qs] - - def get_csv_row(self, obj): - return ( - obj.full_name, - u', '.join([e.email for e in obj.email_set.all()]), - obj.main_mandate.group.abbreviation, - obj.country, - ) - - queryset = Representative.objects.filter( - active=True).select_related('score') +class RepresentativeDetail(RepresentativeViewMixin, generic.DetailView): -class RepresentativeDetail(representatives_views.RepresentativeDetail): queryset = Representative.objects.select_related('score') def get_queryset(self): + qs = super(RepresentativeDetail, self).get_queryset() + + qs = self.prefetch_for_representative_country_and_main_mandate(qs) + social = ['twitter', 'facebook'] - qs = super(RepresentativeDetail, self).get_queryset().prefetch_related( + qs = qs.prefetch_related( 'email_set', models.Prefetch( 'website_set', @@ -71,21 +49,21 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail): '-proposal__datetime') ) ) + return qs def get_context_data(self, **kwargs): c = super(RepresentativeDetail, self).get_context_data(**kwargs) + + self.add_representative_country_and_main_mandate(c['object']) + + c['votes'] = c['object'].votes.all() + c['mandates'] = c['object'].mandates.all() + c['positions'] = c['object'].positions.filter( + published=True).prefetch_related('tags') + c['position_form'] = PositionForm( initial={'representative': self.object.pk}) self.add_representative_country_and_main_mandate(c['object']) return c - - -class DossierList(PaginationMixin, representatives_votes_views.DossierList): - queryset = Dossier.objects.prefetch_related( - 'proposals', - 'proposals__recommendation' - ).annotate( - nb_recomm=Count('proposals__recommendation') - ).order_by('-nb_recomm', '-reference') diff --git a/memopol/views/representative_list.py b/memopol/views/representative_list.py new file mode 100644 index 00000000..6b034abb --- /dev/null +++ b/memopol/views/representative_list.py @@ -0,0 +1,86 @@ +# coding: utf-8 + +from core.views import GridListMixin, PaginationMixin, CSVDownloadMixin + +import datetime + +from django.db import models +from django.utils.text import slugify +from django.views import generic + +from representatives.models import Group, Representative + +from .representative_mixin import RepresentativeViewMixin + + +class RepresentativeList(CSVDownloadMixin, GridListMixin, PaginationMixin, + RepresentativeViewMixin, generic.ListView): + + csv_name = 'meps.csv' + queryset = Representative.objects.filter( + active=True).select_related('score') + + def get_context_data(self, **kwargs): + c = super(RepresentativeList, self).get_context_data(**kwargs) + + c['object_list'] = [ + self.add_representative_country_and_main_mandate(r) + for r in c['object_list'] + ] + + return c + + def search_filter(self, qs): + search = self.request.GET.get('search', None) + if search: + qs = qs.filter(slug__icontains=slugify(search)) + return qs + + def group_filter(self, qs): + group_kind = self.kwargs.get('group_kind', None) + chamber = self.kwargs.get('chamber', None) + group = self.kwargs.get('group', None) + today = datetime.date.today() + + if group_kind and group: + if group.isnumeric(): + group_qs = Group.objects.filter( + id=int(group) + ) + else: + group_qs = Group.objects.filter( + name=group, + kind=group_kind + ) + + if chamber: + group_qs = group_qs.filter(chamber__name=chamber) + + qs = qs.filter( + models.Q(mandates__end_date__gte=today) | + models.Q(mandates__end_date__isnull=True), + mandates__group__in=group_qs + ) + + return qs + + def get_queryset(self): + qs = super(RepresentativeList, self).get_queryset() + qs = self.group_filter(qs) + qs = self.search_filter(qs) + qs = self.prefetch_for_representative_country_and_main_mandate(qs) + return qs + + def get_csv_results(self, context, **kwargs): + qs = super(RepresentativeList, self).get_queryset() + qs = qs.prefetch_related('email_set') + return [self.add_representative_country_and_main_mandate(r) + for r in qs] + + def get_csv_row(self, obj): + return ( + obj.full_name, + u', '.join([e.email for e in obj.email_set.all()]), + obj.main_mandate.group.abbreviation, + obj.country, + ) diff --git a/memopol/views/representative_mixin.py b/memopol/views/representative_mixin.py new file mode 100644 index 00000000..98b27d40 --- /dev/null +++ b/memopol/views/representative_mixin.py @@ -0,0 +1,59 @@ +# coding: utf-8 + +import datetime + +from django.db import models + +from representatives.models import Mandate + + +class RepresentativeViewMixin(object): + """ + A view mixin to add pre-fetched main_mandate and country to Representative + + If a Representative was fetched from a QuerySet that have been through + prefetch_for_representative_country_and_main_mandate(), then + add_representative_country_and_main_mandate(representative) adds the + ``.country`` and ``.main_mandate`` properties "for free" - the prefetch + methods adds an extra query, but gets all. + """ + + def prefetch_for_representative_country_and_main_mandate(self, queryset): + """ + Prefetch Mandates with their Group and Constituency with Country. + """ + mandates = Mandate.objects.order_by( + '-end_date').select_related('constituency__country', 'group', + 'group__chamber') + return queryset.prefetch_related( + models.Prefetch('mandates', queryset=mandates)) + + def add_representative_country_and_main_mandate(self, representative): + """ + Set representative country, main_mandate and chamber. + + Note that this will butcher your database if you don't use + self.prefetch_related. + """ + today = datetime.date.today() + + representative.country = None + representative.main_mandate = None + + for m in representative.mandates.all(): + if m.constituency.country_id and not representative.country: + representative.country = m.constituency.country + + if ((m.end_date is None or m.end_date > today) and + m.group.kind == 'group' and + not representative.main_mandate): + + representative.main_mandate = m + + if representative.country and representative.main_mandate: + break + + if representative.main_mandate: + representative.chamber = representative.main_mandate.group.chamber + + return representative diff --git a/representatives_positions/tests/test_functional.py b/representatives_positions/tests/test_functional.py index 2925229f..f134e41c 100644 --- a/representatives_positions/tests/test_functional.py +++ b/representatives_positions/tests/test_functional.py @@ -29,7 +29,8 @@ class PositionTest(TestCase): def test_create_position(self): response = self.client.post(self.create_url, self.fixture) assert response.status_code == 302 - expected = 'http://testserver%s' % self.mep.get_absolute_url() + mep_url = reverse('representative-detail', args=(self.mep.slug,)) + expected = 'http://testserver%s' % mep_url assert response['Location'] == expected result = Position.objects.get(text='%stext' % self.id()) diff --git a/representatives_positions/views.py b/representatives_positions/views.py index 3b24ef11..4d7d2df1 100644 --- a/representatives_positions/views.py +++ b/representatives_positions/views.py @@ -1,7 +1,8 @@ from django.views import generic from django.db import models +from django.core.urlresolvers import reverse -from representatives.views import RepresentativeViewMixin +from memopol.views.representative_mixin import RepresentativeViewMixin from representatives.models import Mandate from .models import Position @@ -13,7 +14,8 @@ class PositionCreate(generic.CreateView): form_class = PositionForm def get_success_url(self): - return self.object.representative.get_absolute_url() + return reverse('representative-detail', + args=(self.object.representative.slug,)) class PositionDetail(RepresentativeViewMixin, generic.DetailView): diff --git a/templates/_header.haml b/templates/_header.haml index b0dd05f5..ae7cb83a 100644 --- a/templates/_header.haml +++ b/templates/_header.haml @@ -15,23 +15,23 @@ #nav.container-fluid %ul.nav %li - %a{href: "{% url 'representatives:representative-list' %}"} + %a{href: "{% url 'representative-list' %}"} - trans 'Representatives' %li - %a{href: "{% url 'representatives:group-list' kind='country' %}"} + %a{href: "{% url 'group-list' kind='country' %}"} - trans 'Countries' %li - %a{href: "{% url 'representatives:group-list' kind='chamber' %}"} + %a{href: "{% url 'group-list' kind='chamber' %}"} - trans 'Chambers' %li - %a{href: "{% url 'representatives:group-list' kind='group' %}"} + %a{href: "{% url 'group-list' kind='group' %}"} - trans 'Parties' %li - %a{href: "{% url 'representatives:group-list' kind='delegation' %}"} + %a{href: "{% url 'group-list' kind='delegation' %}"} - trans 'Delegations' %li - %a{href: "{% url 'representatives:group-list' kind='committee' %}"} + %a{href: "{% url 'group-list' kind='committee' %}"} - trans 'Committees' %li - %a{href: "{% url 'representatives_votes:dossier-list' %}"} + %a{href: "{% url 'dossier-list' %}"} - trans 'Dossiers' diff --git a/templates/home.haml b/templates/home.haml index 9a9ad928..bd263ed2 100644 --- a/templates/home.haml +++ b/templates/home.haml @@ -5,7 +5,7 @@ %p Memopol is reachable only in <b>reduced functionality mode</b>. By the way, you could access to - <a href="{% url 'representatives:representative-list' %}">the list of MEPs</a>. + <a href="{% url 'representative-list' %}">the list of MEPs</a>. %p You can help on building the new Memopol by <a href="https://wiki.laquadrature.net/Projects/Memopol/Roadmap">coding, translating, de signing, funding, etc...</a>. .col-md-4 diff --git a/templates/representatives/_representative_block.haml b/templates/representatives/_representative_block.haml index ca5797bf..429e2834 100644 --- a/templates/representatives/_representative_block.haml +++ b/templates/representatives/_representative_block.haml @@ -22,17 +22,17 @@ %tr %th Chamber %td< - %a{'href': "{% url 'representatives:representative-list' group_kind='chamber' group=representative.chamber.name %}"} + %a{'href': "{% chamber_url representative.chamber %}"} = representative.chamber|chamber_icon %tr %th Country %td< - %a{:href => "{{ representative.country.get_absolute_url }}"} + %a{:href => "{% country_url representative.country %}"} = representative.country|country_flag %tr %th Party %td< - %a{:href => "{{ representative.main_mandate.group.get_absolute_url }}"} + %a{:href => "{% group_url representative.main_mandate.group %}"} = representative.main_mandate|mandate_icon %tr %th Biography diff --git a/templates/representatives/group_list.haml b/templates/representatives/group_list.haml index 0e41d42f..b009e463 100644 --- a/templates/representatives/group_list.haml +++ b/templates/representatives/group_list.haml @@ -1,22 +1,24 @@ - extends 'base.html' +- load memopol_tags - load representatives_tags + - block content %table.table - for group in object_list %tr - if group.kind != 'country' and group.kind != 'chamber' %td - %a{'href': "{% url 'representatives:representative-list' group_kind='chamber' group=group.chamber.name %}"} + %a{'href': "{% chamber_url group.chamber %}"} = group.chamber|chamber_icon %td - %a{'href': '{{ group.get_absolute_url }}'} + %a{'href': "{% group_url group %}"} - if group.abbreviation ={group.abbreviation} %td - %a{'href': '{{ group.get_absolute_url }}'}= + %a{'href': "{% group_url group %}"}= - if group.kind == 'chamber' = group|chamber_icon - elif group.kind == 'group' diff --git a/templates/representatives/representative_detail.haml b/templates/representatives/representative_detail.haml index 8d3214cd..d2818765 100644 --- a/templates/representatives/representative_detail.haml +++ b/templates/representatives/representative_detail.haml @@ -1,6 +1,7 @@ - extends 'base.html' - load humanize +- load memopol_tags - load representatives_tags - load representatives_votes_tags - load representatives_recommendations_tags @@ -48,7 +49,7 @@ %tr.mandate %td= mandate.role %td - %a{:href => "{{ mandate.group.get_absolute_url }}"} + %a{:href => "{% group_url mandate.group %}"} {{ mandate.group.name }} - if mandate.group.abbreviation {{ mandate.group.abbreviation }} @@ -75,7 +76,7 @@ %span.label.label-default = tag %td - %a{:href => '{{position.link}}'} + %a{:href => '{{ position.link }}'} = position.link - include 'representatives_positions/_form.html' with form=position_form diff --git a/templates/representatives/representative_grid.haml b/templates/representatives/representative_grid.haml index f9270e0e..bc50ad49 100644 --- a/templates/representatives/representative_grid.haml +++ b/templates/representatives/representative_grid.haml @@ -1,5 +1,6 @@ - extends 'representatives/representative_list.html' +- load memopol_tags - load representatives_tags - load representatives_recommendations_tags @@ -9,20 +10,20 @@ - for representative in object_list .representative_item %p.photo - %a{'href': "{{ representative.get_absolute_url }}"} + %a{'href': "{% url 'representative-detail' representative.slug %}"} %img{'src': '={representative.photo}', 'width': '80'}/ %ul %li.name - %a{'href': "{{ representative.get_absolute_url }}"} + %a{'href': "{% url 'representative-detail' representative.slug %}"} = representative.full_name %li.chamber - %a{'href': "{% url 'representatives:representative-list' group_kind='chamber' group=representative.chamber.name %}"} + %a{'href': "{% chamber_url representative.chamber %}"} = representative.chamber|chamber_icon %li.country - %a{'href': "{{ representative.country.get_absolute_url }}"} + %a{'href': "{% country_url representative.country %}"} = representative.country|country_flag %li.mandate - %a{'href': "{{ representative.main_mandate.group.get_absolute_url }}"} + %a{'href': "{% group_url representative.main_mandate.group %}"} = representative.main_mandate.group|group_icon %li.score = representative.score.score|score_label diff --git a/templates/representatives/representative_list.haml b/templates/representatives/representative_list.haml index 5a6c2993..af5c9621 100644 --- a/templates/representatives/representative_list.haml +++ b/templates/representatives/representative_list.haml @@ -1,6 +1,7 @@ - extends 'base.html' - load i18n +- load memopol_tags - load representatives_tags - load representatives_recommendations_tags @@ -39,23 +40,23 @@ - for representative in object_list %tr %td - %a{'href': "{{ representative.get_absolute_url }}"} + %a{'href': "{% url 'representative-detail' representative.slug %}"} %img{'src': '={representative.photo}', 'width': '80'}/ %td - %a{'href': "{{ representative.get_absolute_url }}"} + %a{'href': "{% url 'representative-detail' representative.slug %}"} = representative.full_name %td - %a{'href': "{% url 'representatives:representative-list' group_kind='chamber' group=representative.chamber.name %}"} + %a{'href': "{% chamber_url representative.chamber %}"} = representative.chamber %td - %a{'href': "{{ representative.country.get_absolute_url }}"} + %a{'href': "{% country_url representative.country %}"} = representative.country %td - %a{'href': "{{ representative.main_mandate.group.get_absolute_url }}"} + %a{'href': "{% group_url representative.main_mandate.group %}"} = representative.main_mandate.group|group_icon %td = representative.score.score|score_label diff --git a/templates/representatives_votes/dossier_list.haml b/templates/representatives_votes/dossier_list.haml index 15d1bab1..4bc5df7e 100644 --- a/templates/representatives_votes/dossier_list.haml +++ b/templates/representatives_votes/dossier_list.haml @@ -17,7 +17,7 @@ - for dossier in object_list %tr %td - %a{'href': "{{ dossier.get_absolute_url }}"} + %a{'href': "{% url 'dossier-detail' dossier.pk %}"} {{ dossier.title }} %td= dossier.nb_recomm %td= dossier.reference -- GitLab