From 2dfcfc3f8e44d953bb83b8d0ff0a37b83c99a746 Mon Sep 17 00:00:00 2001 From: Arnaud Fabre <arnaud.fabre@camobscura.fr> Date: Mon, 29 Jun 2015 14:12:46 +0200 Subject: [PATCH] adds TimeStampedModel and HashableModel --- representatives_votes/admin.py | 11 ++-- .../commands/import_dossier_from_toutatis.py | 28 ++++------ representatives_votes/models.py | 24 +++++--- representatives_votes/serializers.py | 9 +-- representatives_votes/{utils.py => tasks.py} | 56 ++++++++++++++++++- 5 files changed, 87 insertions(+), 41 deletions(-) rename representatives_votes/{utils.py => tasks.py} (50%) diff --git a/representatives_votes/admin.py b/representatives_votes/admin.py index c9c2d09..0add978 100644 --- a/representatives_votes/admin.py +++ b/representatives_votes/admin.py @@ -5,13 +5,13 @@ from .models import Dossier, Proposal, Vote class DossierAdmin(admin.ModelAdmin): - list_display = ('reference', 'title', 'link') - search_fields = ('reference', 'title') + list_display = ('id', 'fingerprint', 'reference', 'title', 'link') + search_fields = ('reference', 'title', 'fingerprint') class ProposalAdmin(admin.ModelAdmin): - list_display = ('reference', 'dossier_reference', 'title', 'datetime', 'kind', 'total_abstain', 'total_against', 'total_for') - search_fields = ('reference', 'dossier__reference', 'title',) + list_display = ('id', 'fingerprint', 'reference', 'dossier_reference', 'title', 'datetime', 'kind', 'total_abstain', 'total_against', 'total_for') + search_fields = ('reference', 'dossier__reference', 'title', 'fingerprint') def dossier_reference(self, obj): return obj.dossier.reference @@ -29,6 +29,7 @@ class NoneMatchingFilter(admin.SimpleListFilter): else: return queryset + class VoteAdmin(admin.ModelAdmin): list_display = ('id', 'proposal_reference', 'position', 'representative_name', 'representative_remote_id') list_filter = (NoneMatchingFilter,) @@ -37,7 +38,5 @@ class VoteAdmin(admin.ModelAdmin): return obj.proposal.reference admin.site.register(Dossier, DossierAdmin) - admin.site.register(Proposal, ProposalAdmin) - admin.site.register(Vote, VoteAdmin) diff --git a/representatives_votes/management/commands/import_dossier_from_toutatis.py b/representatives_votes/management/commands/import_dossier_from_toutatis.py index 7978754..dcf3e0a 100644 --- a/representatives_votes/management/commands/import_dossier_from_toutatis.py +++ b/representatives_votes/management/commands/import_dossier_from_toutatis.py @@ -18,25 +18,21 @@ # # Copyright (C) 2013 Laurent Peuch <cortex@worlddomination.be> # Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net> -import json -from urllib2 import urlopen from django.core.management.base import BaseCommand -from django.conf import settings - -from representatives_votes.utils import import_a_dossier +from representatives_votes.tasks import import_a_dossier_from_toutatis class Command(BaseCommand): + """ + Command to import a dossier from a toutatis server + """ + + def add_arguments(self, parser): + parser.add_argument('--celery', action='store_true', default=False) + def handle(self, *args, **options): reference = args[0] - toutatis_server = getattr(settings, - 'TOUTATIS_SERVER', - 'http://toutatis.mm.staz.be') - search_url = toutatis_server + '/api/dossiers/?reference=%s' % reference - print('Import dossier from %s' % search_url) - data = json.load(urlopen(search_url)) - if data['count'] != 1: - raise Exception('Search should return one and only one result') - detail_url = data['results'][0]['url'] - data = json.load(urlopen(detail_url)) - import_a_dossier(data) + if options['celery']: + import_a_dossier_from_toutatis.delay(reference, delay=True) + else: + import_a_dossier_from_toutatis(reference, delay=False) diff --git a/representatives_votes/models.py b/representatives_votes/models.py index 0768ef2..f3b64b2 100644 --- a/representatives_votes/models.py +++ b/representatives_votes/models.py @@ -16,17 +16,27 @@ # License along with django-representatives. # If not, see <http://www.gnu.org/licenses/>. +import hashlib + from django.db import models +from django.utils.functional import cached_property +from django.utils.encoding import smart_str +from representatives.models import TimeStampedModel, HashableModel -class Dossier(models.Model): +class Dossier(HashableModel, TimeStampedModel): title = models.CharField(max_length=1000) reference = models.CharField(max_length=200) text = models.TextField(blank=True, default='') link = models.URLField() + hashable_fields = ['title', 'reference'] + + def __unicode__(self): + return unicode(self.title) + -class Proposal(models.Model): +class Proposal(HashableModel, TimeStampedModel): dossier = models.ForeignKey(Dossier, related_name='proposals') title = models.CharField(max_length=1000) description = models.TextField(blank=True, default='') @@ -37,13 +47,9 @@ class Proposal(models.Model): total_against = models.IntegerField() total_for = models.IntegerField() - # Presentation for the api - def vote_api_list(self): - return [{'position': vote.position, - 'representative_remote_id': vote.representative_remote_id, - 'representative_name': vote.representative_name - } - for vote in self.vote_set.all()] + hashable_fields = ['dossier', 'title', 'reference', 'kind'] + def __unicode__(self): + return unicode(self.title) class Vote(models.Model): diff --git a/representatives_votes/serializers.py b/representatives_votes/serializers.py index 753ed8a..1ad2f50 100644 --- a/representatives_votes/serializers.py +++ b/representatives_votes/serializers.py @@ -45,6 +45,7 @@ class ProposalSerializer(serializers.ModelSerializer): model = models.Proposal fields = ( 'id', + 'fingerprint', 'title', 'description', 'reference', @@ -116,6 +117,7 @@ class DossierSerializer(serializers.ModelSerializer): model = models.Dossier fields = ( 'id', + 'fingerprint', 'title', 'reference', 'text', @@ -134,13 +136,6 @@ class DossierListSerializer(DossierSerializer): 'url', ) + ProposalSerializer.Meta.fields - ''' - proposals = serializers.HyperlinkedRelatedField( - many=True, - read_only=True, - view_name='proposal-detail', - ) - ''' proposals = ProposalSerializer( many = True, diff --git a/representatives_votes/utils.py b/representatives_votes/tasks.py similarity index 50% rename from representatives_votes/utils.py rename to representatives_votes/tasks.py index 71f0d36..a0aff2b 100644 --- a/representatives_votes/utils.py +++ b/representatives_votes/tasks.py @@ -18,18 +18,68 @@ # # Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net> +from __future__ import absolute_import + +import logging +import json + +from django.conf import settings + +# import redis +from celery import shared_task +from urllib2 import urlopen + from representatives_votes.models import Dossier from representatives_votes.serializers import DossierDetailSerializer -# Import a dossier -def import_a_dossier(data): +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +steam_handler = logging.StreamHandler() +steam_handler.setLevel(logging.DEBUG) +logger.addHandler(steam_handler) +@shared_task +def import_a_dossier(data): + ''' + Import a dossier from serialized + ''' serializer = DossierDetailSerializer(data=data) if serializer.is_valid(): serializer.save() else: print(serializer.errors) - + +@shared_task +def import_a_dossier_from_toutatis(fingerprint, delay=False): + ''' + Import a complete dossier from a toutatis server + ''' + + toutatis_server = getattr(settings, + 'TOUTATIS_SERVER', + 'http://toutatis.mm.staz.be') + search_url = '{server}/api/dossiers/?fingerprint={fingerprint}'.format({ + 'server': toutatis_server, + 'fingerprint': fingerprint + }) + logger.info('Import dossier from {}'.format(search_url)) + data = json.load(urlopen(search_url)) + if data['count'] != 1: + raise Exception('Search should return one and only one result') + detail_url = data['results'][0]['url'] + data = json.load(urlopen(detail_url)) + if delay: + import_a_dossier.delay(data) + else: + import_a_dossier(data) + +@shared_task +def import_a_proposal_from_toutatis(fingerprint, delay=False): + ''' + Import a partial dossier from a toutatis server + ''' + pass + def import_dossiers(data): return [import_a_dossier(d_data) for d_data in data] -- GitLab