Commit 5280efb4 authored by Arnaud Fabre's avatar Arnaud Fabre

updates dossier serializers

parent b89d3035
# coding: utf-8
# This file is part of toutatis.
#
# toutatis is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# toutatis is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with Foobar.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2013 Laurent Peuch <cortex@worlddomination.be>
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
import json
import urllib2
from urllib2 import urlopen
from django.core.management.base import BaseCommand
from django.conf import settings
from representatives_votes.utils import import_a_dossier
class Command(BaseCommand):
def handle(self, *args, **options):
dossier_ref = args[0]
print(dossier_ref)
reference = args[0]
toutatis_server = getattr(settings,
'TOUTATIS_SERVER',
'http://toutatis.mm.staz.be')
search_url = toutatis_server + '/api/dossiers/?reference=%s' % reference
data = json.load(urlopen(search_url))
if len(data) != 1:
raise Exception('Search should return one and only one result')
detail_url = data[0]['url']
data = json.load(urlopen(detail_url))
import_a_dossier(data)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('representatives_votes', '0005_auto_20150521_1529'),
]
operations = [
migrations.AlterField(
model_name='dossier',
name='text',
field=models.TextField(null=True, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='proposal',
name='description',
field=models.TextField(null=True, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='proposal',
name='dossier',
field=models.ForeignKey(related_name='proposals', to='representatives_votes.Dossier'),
preserve_default=True,
),
migrations.AlterField(
model_name='vote',
name='proposal',
field=models.ForeignKey(related_name='votes', to='representatives_votes.Proposal'),
preserve_default=True,
),
]
# coding: utf-8
# This file is part of toutatis.
#
# toutatis is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# toutatis is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
from django.db import models
class Dossier(models.Model):
title = models.CharField(max_length=1000)
reference = models.CharField(max_length=200)
text = models.TextField()
text = models.TextField(blank=True, null=True)
link = models.URLField()
class Proposal(models.Model):
dossier = models.ForeignKey(Dossier)
dossier = models.ForeignKey(Dossier, related_name='proposals')
title = models.CharField(max_length=1000)
description = models.TextField()
description = models.TextField(blank=True, null=True)
reference = models.CharField(max_length=200, null=True)
datetime = models.DateTimeField()
kind = models.CharField(max_length=200, null=True)
......@@ -28,7 +44,7 @@ class Proposal(models.Model):
'representative_name': vote.representative_name
}
for vote in self.vote_set.all()]
class Vote(models.Model):
VOTECHOICES = (
......@@ -37,7 +53,7 @@ class Vote(models.Model):
('against', 'against')
)
proposal = models.ForeignKey(Proposal)
proposal = models.ForeignKey(Proposal, related_name='votes')
# There are two representative fields for flexibility,
representative_name = models.CharField(max_length=200, blank=True, null=True)
......
# coding: utf-8
# This file is part of toutatis.
#
# toutatis is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# toutatis is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
import representatives_votes.models as models
from rest_framework import serializers
from django.db import transaction
from django.db import connection
from django.db.utils import OperationalError
def truncate_model(model):
cursor = connection.cursor()
try:
cursor.execute('TRUNCATE TABLE "{0}"'.format(model._meta.db_table))
except OperationalError:
cursor.execute('DELETE FROM "{0}"'.format(model._meta.db_table))
class VoteSerializer(serializers.ModelSerializer):
'''
Serializer for votes
'''
class Meta:
model = models.Vote
fields = (
'representative_name',
'representative_remote_id',
'position'
)
class ProposalSerializer(serializers.ModelSerializer):
'''
Base Proposal Serializer
'''
class Meta:
model = models.Proposal
fields = (
'title',
'description',
'reference',
'datetime',
'kind',
'total_abstain',
'total_against',
'total_for',
)
class ProposalHyperLinkedSerializer(ProposalSerializer):
'''
Proposal Serializer with hyperlink to dossier (used for listing)
'''
dossier = serializers.HyperlinkedRelatedField(
read_only = True,
view_name = 'dossier-detail',
)
class Meta(ProposalSerializer.Meta):
fields = ('dossier', 'url',) + ProposalSerializer.Meta.fields
class ProposalDetailSerializer(ProposalSerializer):
'''
Proposal Serializer with votes detail (used in Dossier Detail)
'''
votes = VoteSerializer(many=True)
class Meta(ProposalSerializer.Meta):
fields = ProposalSerializer.Meta.fields + (
'votes',
)
class ProposalDetailHyperLinkedSerializer(ProposalDetailSerializer, ProposalHyperLinkedSerializer):
'''
Proposal Serializer combined Detail Serializer and Hyperlinked Serializer
'''
class Meta(ProposalSerializer.Meta):
fields = ('dossier',) + ProposalSerializer.Meta.fields + (
'votes',
)
class DossierSerializer(serializers.ModelSerializer):
'''
Base Dossier Serializer
'''
class Meta:
model = models.Dossier
fields = (
'title',
'reference',
'text',
'link',
)
class DossierHyperLinkedSerializer(DossierSerializer):
'''
Dossier Serializer with hyperlinks to proposals
'''
proposals = serializers.HyperlinkedRelatedField(
many=True,
read_only=True,
view_name='proposal-detail',
)
class Meta(DossierSerializer.Meta):
fields = DossierSerializer.Meta.fields + (
'url',
'proposals',
)
class DossierDetailSerializer(DossierSerializer):
'''
Dossier Serializer with proposals details
'''
proposals = ProposalDetailSerializer(
many=True,
)
class Meta(DossierSerializer.Meta):
fields = DossierSerializer.Meta.fields + (
'proposals',
)
@transaction.atomic
def create(self, validated_data):
proposals_data = validated_data.pop('proposals')
dossier, _ = models.Dossier.objects.get_or_create(**validated_data)
self._create_proposals(proposals_data, dossier)
return dossier
def _create_proposals(self, proposals_data, dossier):
truncate_model(models.Proposal)
truncate_model(models.Vote)
for proposal_data in proposals_data:
votes_data = proposal_data.pop('votes')
proposal_data['dossier'] = dossier
proposal = models.Proposal.objects.create(**proposal_data)
for vote_data in votes_data:
vote_data['proposal'] = proposal
models.Vote.objects.create(**vote_data)
from dateutil.parser import parse as date_parse
from .models import Dossier, Proposal, Vote
import datetime
# Export
def export_all_dossiers():
return [export_a_dossier(dossier) for dossier in Dossier.objects.all()]
# coding: utf-8
# This file is part of toutatis.
#
# toutatis is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# toutatis is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from representatives_votes.models import Dossier
from representatives_votes.serializers import DossierDetailSerializer
# Import a dossier
def import_a_dossier(data):
serializer = DossierDetailSerializer(data=data)
print(serializer.is_valid())
print(serializer.save())
def import_dossiers(data):
return [import_a_dossier(d_data) for d_data in data]
# Export a dossier
def export_a_dossier(dossier):
ret = {'dossier': {
'title': dossier.title,
'reference': dossier.reference,
'text': dossier.text
}}
ret['proposals'] = [export_a_proposal(proposal) for proposal in dossier.proposal_set.all()]
return ret
def export_a_proposal(proposal):
ret = {
'title': proposal.title,
'reference': proposal.reference,
'description': proposal.description,
'datetime': proposal.datetime.isoformat(),
'kind': proposal.kind,
'total_abstain': proposal.total_abstain,
'total_against': proposal.total_against,
'total_for': proposal.total_for
}
ret['votes'] = [export_a_vote(vote) for vote in proposal.vote_set.all()]
return ret
serialized = DossierDetailSerializer(dossier)
return serialized.data
def export_a_vote(vote):
return {
'representative_name': vote.representative_name,
'representative_remote_id': vote.representative_remote_id,
'postion': vote.position
}
# Import
def import_a_dossier(dossier_data):
dossier, created = Dossier.objects.get_or_create(reference=dossier_data['reference'])
if created:
dossier_attr = ['title', 'text', 'link']
for attr in dossier_attr:
setattr(dossier, attr, dossier_data[attr])
dossier.save()
dossier.proposal_set.all().delete()
for proposal_data in dossier_data['proposals']:
import_a_proposal(proposal_data, dossier)
def import_a_proposal(proposal_data, dossier):
proposal = Proposal.objects.create(
dossier=dossier,
title=proposal_data['title'],
description=proposal_data['description'],
reference=proposal_data['reference'],
datetime=date_parse(proposal_data['datetime']),
kind=proposal_data['kind'],
total_abstain=proposal_data['total_abstain'],
total_against=proposal_data['total_against'],
total_for=proposal_data['total_for']
)
for vote_data in proposal_data['votes']:
import_a_vote(vote_data, proposal)
def export_dossiers(filters={}):
return [export_a_dossier(dossier) for dossier in Dossier.objects.filter(**filters)]
def import_a_vote(vote_data, proposal):
vote_data['proposal'] = proposal
Vote.objects.create(**vote_data)
def export_all_dossier():
return export_dossiers()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment