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

Francedata fixes #27

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ install:
- pip install $DJANGO pep8 flake8 pytest-django pytest-cov codecov django-responsediff
- pip install -e .[api]
script:
- pep8 representatives/ --exclude migrations --ignore E128
- flake8 representatives/ --exclude migrations --ignore E128
- django-admin migrate
- cat representatives/contrib/francedata/tests/representatives_input.json | francedata_import_representatives
Expand Down
63 changes: 40 additions & 23 deletions representatives/contrib/francedata/import_representatives.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import django
from django.apps import apps
from django.db import transaction
from django.db import DatabaseError
from django.utils import timezone

from representatives.models import (Country, Mandate, Email, Address, WebSite,
Expand Down Expand Up @@ -43,21 +44,6 @@ def _parse_date(date):
return datetime.strptime(date, "%Y-%m-%d").date()


def _create_mandate(representative, group, constituency, role='',
begin_date=None, end_date=None):
mandate, _ = Mandate.objects.get_or_create(
representative=representative,
group=group,
constituency=constituency,
role=role,
begin_date=begin_date,
end_date=end_date
)

if _:
logger.debug('Created mandate %s', mandate.pk)


def _get_path(dict_, path):
'''
Get value at specific path in dictionary. Path is specified by slash-
Expand All @@ -80,12 +66,25 @@ def touch_model(self, model, **data):
it saves the given model if it exists, updating its
updated field
'''

instance, created = model.objects.get_or_create(**data)
model_name = model._meta.verbose_name
data_string = repr(data).decode('utf8')
logger.debug('Saving %s with %s' % (model_name, data_string))
try:
with transaction.atomic():
instance, created = model.objects.get_or_create(**data)
except DatabaseError as e:
logger.error('Saving %s failed: %s' % (model_name, e))
return False, False

if not created:
if instance.updated < self.import_start_datetime:
instance.save() # Updates updated field
logger.debug('Updating %s with %s' % (model_name, data_string))
try:
with transaction.atomic():
instance.save()
except DatabaseError as e:
logger.error('Saving %s failed: %s' % (model_name, e))
return False, False

return (instance, created)

Expand Down Expand Up @@ -180,15 +179,18 @@ def add_mandates(self, representative, rep_json):

# Mandate in country group for party constituency
if rep_json.get('parti_ratt_financier'):
constituency, _ = Constituency.objects.get_or_create(
name=rep_json.get('parti_ratt_financier'), country=self.france)
constituency, _ = self.touch_model(
model=Constituency,
name=rep_json.get('parti_ratt_financier'),
country=self.france
)

group, _ = self.touch_model(model=Group,
abbreviation=self.france.code,
kind='country',
name=self.france.name)

_create_mandate(representative, group, constituency, 'membre')
self._create_mandate(representative, group, constituency, 'membre')

# Configurable mandates
for mdef in self.variant['mandates']:
Expand All @@ -212,6 +214,9 @@ def add_mandates(self, representative, rep_json):
chamber=chamber,
name=name)

if group is False:
continue

role = _get_mdef_item(mdef, 'role', elem, 'membre')
start = _get_mdef_item(mdef, 'start', elem, None)
if start is not None:
Expand All @@ -220,8 +225,8 @@ def add_mandates(self, representative, rep_json):
if end is not None:
end = _parse_date(end)

_create_mandate(representative, group, self.ch_constituency,
role, start, end)
self._create_mandate(representative, group,
self.ch_constituency, role, start, end)

logger.debug(
'%s => %s: %s of "%s" (%s) %s-%s' % (rep_json['slug'],
Expand Down Expand Up @@ -300,6 +305,18 @@ def add_contacts(self, representative, rep_json):
kind='', number=item['tel']
)

def _create_mandate(self, representative, group, constituency, role='',
begin_date=None, end_date=None):
mandate, _ = self.touch_model(
model=Mandate,
representative=representative,
group=group,
constituency=constituency,
role=role,
begin_date=begin_date,
end_date=end_date
)


def main(stream=None):
if not apps.ready:
Expand Down
19 changes: 19 additions & 0 deletions representatives/migrations/0017_increment_mandate_role_size.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('representatives', '0016_chamber_migrate_data'),
]

operations = [
migrations.AlterField(
model_name='mandate',
name='role',
field=models.CharField(default=b'', help_text=b'Eg.: president of a political group', max_length=255, blank=True),
),
]
18 changes: 16 additions & 2 deletions representatives/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ class Chamber(HashableModel):

hashable_fields = ['name', 'country', 'abbreviation']
Copy link
Member

Choose a reason for hiding this comment

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

Couldn't we get rid of hashable_fields and use the metaclass unique_together attribute in HashableModel.compute_hash ? That would avoid duplicating code.

(also is Meta.unique_together parsed by django-admin makemigrations ? or do we have to create the migration manually ?)


class Meta:
unique_together = [
['name', 'country', 'abbreviation']
]

def __unicode__(self):
return u'{} [{}]'.format(self.name, self.abbreviation)

Expand All @@ -200,6 +205,9 @@ def __unicode__(self):

class Meta:
ordering = ('name',)
unique_together = [
['name', 'abbreviation', 'kind', 'chamber']
]

def get_absolute_url(self):
if self.chamber:
Expand All @@ -219,7 +227,7 @@ class Constituency(HashableModel, TimeStampedModel):
country = models.ForeignKey('Country', null=True, blank=True,
related_name='constituencies')

hashable_fields = ['name']
hashable_fields = ['name', 'country']
Copy link
Member

Choose a reason for hiding this comment

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

Commit no longer needed


@cached_property
def active(self):
Expand Down Expand Up @@ -248,7 +256,7 @@ class Mandate(HashableModel, TimeStampedModel):
Constituency, null=True, related_name='mandates')
representative = models.ForeignKey(Representative, related_name='mandates')
role = models.CharField(
max_length=25,
max_length=255,
Copy link
Member

Choose a reason for hiding this comment

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

Commit no longer needed

blank=True,
default='',
help_text="Eg.: president of a political group"
Expand Down Expand Up @@ -276,3 +284,9 @@ def __unicode__(self):

class Meta:
ordering = ('-end_date',)
unique_together = [
[
'group', 'constituency', 'role', 'begin_date',
'end_date', 'representative'
]
]