Skip to content
Extraits de code Groupes Projets
Valider e5dad7d7 rédigé par Nicolas Joyard's avatar Nicolas Joyard
Parcourir les fichiers

Integrate views removed from django-representatives[-votes]

parent 31deff01
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 406 ajouts et 105 suppressions
...@@ -23,14 +23,16 @@ from representatives_recommendations.api import ( ...@@ -23,14 +23,16 @@ from representatives_recommendations.api import (
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'constituencies', ConstituencyViewSet) router.register(r'constituencies', ConstituencyViewSet, 'api-constituency')
router.register(r'dossiers', DossierViewSet) router.register(r'dossiers', DossierViewSet, 'api-dossier')
router.register(r'dossier_scores', DossierScoreViewSet) router.register(r'dossier_scores', DossierScoreViewSet, 'api-dossierscore')
router.register(r'groups', GroupViewSet) router.register(r'groups', GroupViewSet, 'api-group')
router.register(r'mandates', MandateViewSet) router.register(r'mandates', MandateViewSet, 'api-mandate')
router.register(r'proposals', ProposalViewSet) router.register(r'proposals', ProposalViewSet, 'api-proposal')
router.register(r'recommendations', RecommendationViewSet) router.register(r'recommendations', RecommendationViewSet,
router.register(r'representatives', RepresentativeViewSet) 'api-recommendation')
router.register(r'scores', RepresentativeScoreViewSet) router.register(r'representatives', RepresentativeViewSet,
router.register(r'vote_scores', VoteScoreViewSet) 'api-representative')
router.register(r'votes', VoteViewSet) router.register(r'scores', RepresentativeScoreViewSet, 'api-score')
router.register(r'vote_scores', VoteScoreViewSet, 'api-votescore')
router.register(r'votes', VoteViewSet, 'api-vote')
# coding: utf-8 # coding: utf-8
import re
from django import template from django import template
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
import re from django.utils.html import escape
register = template.Library() register = template.Library()
link = '<a class="{network}-link" href="{url}" target="_blank">{label}</a>' link = '<a class="{network}-link" href="{url}" target="_blank">{label}</a>'
...@@ -30,3 +34,34 @@ def website_link(url): ...@@ -30,3 +34,34 @@ def website_link(url):
def email_link(address): def email_link(address):
return mark_safe(link.format(network='email', url='mailto:%s' % address, return mark_safe(link.format(network='email', url='mailto:%s' % address,
label=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
}))
...@@ -43,27 +43,27 @@ ...@@ -43,27 +43,27 @@
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/country/'> <a href='/legislature/group/country/'>
Countries Countries
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/chamber/'> <a href='/legislature/group/chamber/'>
Chambers Chambers
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/group/'> <a href='/legislature/group/group/'>
Parties Parties
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/delegation/'> <a href='/legislature/group/delegation/'>
Delegations Delegations
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/committee/'> <a href='/legislature/group/committee/'>
Committees Committees
</a> </a>
</li> </li>
......
...@@ -43,27 +43,27 @@ ...@@ -43,27 +43,27 @@
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/country/'> <a href='/legislature/group/country/'>
Countries Countries
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/chamber/'> <a href='/legislature/group/chamber/'>
Chambers Chambers
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/group/'> <a href='/legislature/group/group/'>
Parties Parties
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/delegation/'> <a href='/legislature/group/delegation/'>
Delegations Delegations
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/committee/'> <a href='/legislature/group/committee/'>
Committees Committees
</a> </a>
</li> </li>
......
...@@ -43,27 +43,27 @@ ...@@ -43,27 +43,27 @@
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/country/'> <a href='/legislature/group/country/'>
Countries Countries
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/chamber/'> <a href='/legislature/group/chamber/'>
Chambers Chambers
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/group/'> <a href='/legislature/group/group/'>
Parties Parties
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/delegation/'> <a href='/legislature/group/delegation/'>
Delegations Delegations
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/committee/'> <a href='/legislature/group/committee/'>
Committees Committees
</a> </a>
</li> </li>
......
...@@ -43,27 +43,27 @@ ...@@ -43,27 +43,27 @@
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/country/'> <a href='/legislature/group/country/'>
Countries Countries
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/chamber/'> <a href='/legislature/group/chamber/'>
Chambers Chambers
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/group/'> <a href='/legislature/group/group/'>
Parties Parties
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/delegation/'> <a href='/legislature/group/delegation/'>
Delegations Delegations
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/committee/'> <a href='/legislature/group/committee/'>
Committees Committees
</a> </a>
</li> </li>
......
...@@ -43,27 +43,27 @@ ...@@ -43,27 +43,27 @@
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/country/'> <a href='/legislature/group/country/'>
Countries Countries
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/chamber/'> <a href='/legislature/group/chamber/'>
Chambers Chambers
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/group/'> <a href='/legislature/group/group/'>
Parties Parties
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/delegation/'> <a href='/legislature/group/delegation/'>
Delegations Delegations
</a> </a>
</li> </li>
<li> <li>
<a href='/legislature/groups/committee/'> <a href='/legislature/group/committee/'>
Committees Committees
</a> </a>
</li> </li>
......
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
from django.test import TestCase from django.test import TestCase
from responsediff.response import Response from responsediff.response import Response
from .base import UrlGetTestMixin from .base import UrlGetTestMixin
from representatives.models import Representative
from ..views.representative_mixin import RepresentativeViewMixin
class RepresentativeListTest(UrlGetTestMixin, TestCase): class RepresentativeListTest(UrlGetTestMixin, TestCase):
fixtures = ['smaller_sample.json'] fixtures = ['smaller_sample.json']
url = '/legislature/representative/' 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=''): def functional_test(self, page, paginate_by, display, search=''):
url = '%s?page=%s&search=%s' % (self.url, page, search) url = '%s?page=%s&search=%s' % (self.url, page, search)
......
...@@ -3,7 +3,13 @@ from django.conf.urls import include, url ...@@ -3,7 +3,13 @@ from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.views import generic 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 import api
admin.autodiscover() admin.autodiscover()
...@@ -11,32 +17,58 @@ admin.autodiscover() ...@@ -11,32 +17,58 @@ admin.autodiscover()
urlpatterns = [ urlpatterns = [
# Project-specific overrides # Project-specific overrides
url( url(
r'^legislature/representative/(?P<group_kind>\w+)/(?P<chamber>.+)/' + r'^legislature/representatives?/(?P<group_kind>\w+)/(?P<chamber>.+)/' +
r'(?P<group>.+)/$', 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( url(
r'^legislature/representative/(?P<group_kind>\w+)/(?P<group>.+)/$', r'^votes/dossiers?/$',
views.RepresentativeList.as_view(), DossierList.as_view(),
name='dossier-list'
), ),
url( url(
r'^legislature/representative/(?P<slug>[-\w]+)/$', r'^votes/dossiers?/(?P<pk>\d+)/$',
views.RepresentativeDetail.as_view(), DossierDetail.as_view(),
name='dossier-detail'
), ),
url( url(
r'^legislature/representative/$', r'^votes/autocomplete/dossier/$',
views.RepresentativeList.as_view(), DossierAutocomplete.as_view(),
name='dossier-autocomplete',
), ),
url( url(
r'^votes/dossier/$', r'^votes/autocomplete/proposal/$',
views.DossierList.as_view(), ProposalAutocomplete.as_view(),
name='proposal-autocomplete',
), ),
url(r'^admin/', include(admin.site.urls)), 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', url(r'^positions/', include('representatives_positions.urls',
namespace='representatives_positions')), namespace='representatives_positions')),
url(r'^api/', include(api.router.urls)), url(r'^api/', include(api.router.urls)),
......
# 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
# coding: utf-8
from django.views import generic
from representatives_votes.models import Dossier
class DossierDetail(generic.DetailView):
model = Dossier
# 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')
# 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')
# Project specific "glue" coupling of all apps # coding: utf-8
from django.db import models 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.models import Representative, Address, Phone, WebSite
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_positions.forms import PositionForm from representatives_positions.forms import PositionForm
from representatives_recommendations.models import VoteScore 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') queryset = Representative.objects.select_related('score')
def get_queryset(self): def get_queryset(self):
qs = super(RepresentativeDetail, self).get_queryset()
qs = self.prefetch_for_representative_country_and_main_mandate(qs)
social = ['twitter', 'facebook'] social = ['twitter', 'facebook']
qs = super(RepresentativeDetail, self).get_queryset().prefetch_related( qs = qs.prefetch_related(
'email_set', 'email_set',
models.Prefetch( models.Prefetch(
'website_set', 'website_set',
...@@ -71,21 +49,21 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail): ...@@ -71,21 +49,21 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail):
'-proposal__datetime') '-proposal__datetime')
) )
) )
return qs return qs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
c = super(RepresentativeDetail, self).get_context_data(**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( c['position_form'] = PositionForm(
initial={'representative': self.object.pk}) initial={'representative': self.object.pk})
self.add_representative_country_and_main_mandate(c['object']) self.add_representative_country_and_main_mandate(c['object'])
return c 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')
# 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,
)
# 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
...@@ -29,7 +29,8 @@ class PositionTest(TestCase): ...@@ -29,7 +29,8 @@ class PositionTest(TestCase):
def test_create_position(self): def test_create_position(self):
response = self.client.post(self.create_url, self.fixture) response = self.client.post(self.create_url, self.fixture)
assert response.status_code == 302 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 assert response['Location'] == expected
result = Position.objects.get(text='%stext' % self.id()) result = Position.objects.get(text='%stext' % self.id())
......
from django.views import generic from django.views import generic
from django.db import models 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 representatives.models import Mandate
from .models import Position from .models import Position
...@@ -13,7 +14,8 @@ class PositionCreate(generic.CreateView): ...@@ -13,7 +14,8 @@ class PositionCreate(generic.CreateView):
form_class = PositionForm form_class = PositionForm
def get_success_url(self): 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): class PositionDetail(RepresentativeViewMixin, generic.DetailView):
......
...@@ -15,23 +15,23 @@ ...@@ -15,23 +15,23 @@
#nav.container-fluid #nav.container-fluid
%ul.nav %ul.nav
%li %li
%a{href: "{% url 'representatives:representative-list' %}"} %a{href: "{% url 'representative-list' %}"}
- trans 'Representatives' - trans 'Representatives'
%li %li
%a{href: "{% url 'representatives:group-list' kind='country' %}"} %a{href: "{% url 'group-list' kind='country' %}"}
- trans 'Countries' - trans 'Countries'
%li %li
%a{href: "{% url 'representatives:group-list' kind='chamber' %}"} %a{href: "{% url 'group-list' kind='chamber' %}"}
- trans 'Chambers' - trans 'Chambers'
%li %li
%a{href: "{% url 'representatives:group-list' kind='group' %}"} %a{href: "{% url 'group-list' kind='group' %}"}
- trans 'Parties' - trans 'Parties'
%li %li
%a{href: "{% url 'representatives:group-list' kind='delegation' %}"} %a{href: "{% url 'group-list' kind='delegation' %}"}
- trans 'Delegations' - trans 'Delegations'
%li %li
%a{href: "{% url 'representatives:group-list' kind='committee' %}"} %a{href: "{% url 'group-list' kind='committee' %}"}
- trans 'Committees' - trans 'Committees'
%li %li
%a{href: "{% url 'representatives_votes:dossier-list' %}"} %a{href: "{% url 'dossier-list' %}"}
- trans 'Dossiers' - trans 'Dossiers'
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter