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

cleanup cruft from previous data years #194

Merged
merged 8 commits into from
Feb 7, 2024
Merged
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ __pycache__
/static
*.csv
.env
!_data/raw/offices.csv
!_data/raw/offices.csv
\#*
47 changes: 47 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black

- repo: https://github.com/pycqa/flake8
rev: "9f60881"
hooks:
- id: flake8
args: [--config=.flake8]

- repo: https://github.com/rtts/djhtml
rev: v1.5.1 # replace with the latest tag on GitHub
hooks:
- id: djhtml
# Indent only HTML files in template directories
files: .*/templates/.*\.html$
args: [--tabwidth=2] # tabs should be 2 spaces in Django templates

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.5.1
hooks:
- id: prettier
files: \.(js|ts|jsx|tsx|css|less|json|markdown|md|yaml|yml)$

- repo: https://github.com/pre-commit/mirrors-eslint
rev: "1f7d592"
hooks:
- id: eslint
additional_dependencies:
- [email protected]
- [email protected]
- [email protected]

- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
Binary file removed CON_2023.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ docker-compose build
Next, load in data and build your search index:

```bash
docker-compose run --rm app python manage.py import_data
docker-compose run --rm app python make nightly
docker-compose run --rm app python manage.py make_search_index
```

Expand Down
1,029 changes: 0 additions & 1,029 deletions _data/raw/offices.csv

This file was deleted.

22 changes: 0 additions & 22 deletions appspec.yml

This file was deleted.

107 changes: 58 additions & 49 deletions camp_fin/admin.py
Original file line number Diff line number Diff line change
@@ -1,135 +1,144 @@
from django.contrib import admin
from django import forms
from django.contrib import admin
from django.core.management import call_command

from camp_fin.models import Race, RaceGroup, Campaign, Story
from camp_fin.decorators import short_description, boolean
from camp_fin.decorators import boolean, short_description
from camp_fin.models import Campaign, Race, RaceGroup, Story


class ClearCacheMixin(object):
'''
"""
Mixin that overrides the `save` and `delete` methods of Django's ModelAdmin
class to clear the cache whenever an object is added or changed.
'''
"""

def save_model(self, request, obj, form, change):
call_command('clear_cache')
call_command("clear_cache")
super().save_model(request, obj, form, change)

def delete_model(self, request, obj):
call_command('clear_cache')
call_command("clear_cache")
super().delete_model(request, obj)


def create_display(obj, attr, field):
'''
"""
Utility function for generating display values for ForeignKey form fields
on the Admin page.
'''
"""
attribute = getattr(getattr(obj, attr), field, None)

if attribute:
return attribute
else:
return '--'
return "--"


class WinnerFilter(admin.SimpleListFilter):
'''
"""
Filter Races based on whether they have a Winner or not.
'''
title = 'whether a winner exists'
parameter_name = 'winner'
"""

title = "whether a winner exists"
parameter_name = "winner"

def lookups(self, request, model_admin):
'''
"""
Filter options that the user can choose, in the form:

(<parameter>, <human_readable_string>)
'''
"""
return (
('yes', 'Yes'),
('no', 'No'),
("yes", "Yes"),
("no", "No"),
)

def queryset(self, request, queryset):
'''
"""
Restrict the queryset based on the parameter the user has chosen.
'''
"""

if self.value() == 'yes':
if self.value() == "yes":
return queryset.filter(winner__isnull=False)

elif self.value() == 'no':
elif self.value() == "no":
return queryset.filter(winner__isnull=True)


class RaceForm(forms.ModelForm):

class Meta:
model = Race
fields = ['winner']
fields = ["winner"]

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['winner'].queryset = Campaign.objects\
.filter(active_race__id=self.instance.id)

self.fields["winner"].queryset = Campaign.objects.filter(
active_race__id=self.instance.id
)


@admin.register(Story)
class StoryAdmin(admin.ModelAdmin, ClearCacheMixin):
relevant_fields = ('title', 'link')
relevant_fields = ("title", "link")
list_display = relevant_fields
search_fields = ('title', 'link')
search_fields = ("title", "link")


class CampaignInline(admin.StackedInline, ClearCacheMixin):
model = Campaign
fields = ('race_status',)
fields = ("race_status",)
extra = 0


@admin.register(Race)
class RaceAdmin(admin.ModelAdmin, ClearCacheMixin):
relevant_fields = ('__str__', 'display_division', 'display_district',
'display_office', 'display_office_type', 'display_county',
'display_election_season', 'display_candidates', 'has_winner')
relevant_fields = (
"__str__",
"display_division",
"display_district",
"display_office",
"display_office_type",
"display_county",
"display_election_season",
"display_candidates",
"has_winner",
)

list_display = relevant_fields
list_filter = (WinnerFilter, 'election_season__year')
list_filter = (WinnerFilter, "election_season__year")
form = RaceForm
search_fields = ('office__description',)
search_fields = ("office__description",)
inlines = [CampaignInline]

@short_description('Division')
@short_description("Division")
def display_division(self, obj):
return create_display(obj, 'division', 'name')
return create_display(obj, "division", "name")

@short_description('District')
@short_description("District")
def display_district(self, obj):
return create_display(obj, 'district', 'name')
return create_display(obj, "district", "name")

@short_description('Office')
@short_description("Office")
def display_office(self, obj):
return create_display(obj, 'office', 'description')
return create_display(obj, "office", "description")

@short_description('Office Type')
@short_description("Office Type")
def display_office_type(self, obj):
return create_display(obj, 'office_type', 'description')
return create_display(obj, "office_type", "description")

@short_description('County')
@short_description("County")
def display_county(self, obj):
return create_display(obj, 'county', 'name')
return create_display(obj, "county", "name")

@short_description('Season')
@short_description("Season")
def display_election_season(self, obj):
return create_display(obj, 'election_season', 'year')
return create_display(obj, "election_season", "year")

@short_description('Candidates')
@short_description("Candidates")
def display_candidates(self, obj):
return obj.num_candidates

@short_description('Winner')
@short_description("Winner")
@boolean
def has_winner(self, obj):
return obj.winner is not None
Expand Down
16 changes: 8 additions & 8 deletions camp_fin/api_parts.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import csv
from io import StringIO, BytesIO
import re
import zipfile
from io import BytesIO, StringIO

from rest_framework import serializers, pagination, renderers
from rest_framework import pagination, renderers, serializers
from rest_framework_csv.renderers import CSVStreamingRenderer

from camp_fin.models import (
Candidate,
PAC,
Transaction,
LoanTransaction,
Loan,
Treasurer,
Address,
Candidate,
Loan,
LoanTransaction,
Lobbyist,
Organization,
LobbyistTransaction,
Organization,
Transaction,
Treasurer,
)


Expand Down
4 changes: 2 additions & 2 deletions camp_fin/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


class CampFinConfig(AppConfig):
name = 'camp_fin'
verbose_name = 'Campaign Finance'
name = "camp_fin"
verbose_name = "Campaign Finance"

def ready(self):
# Import signal handlers
Expand Down
22 changes: 10 additions & 12 deletions camp_fin/base_views.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import csv
from collections import namedtuple
from datetime import datetime
import csv

from django.views.generic import ListView, DetailView, TemplateView
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.http import JsonResponse, StreamingHttpResponse
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import connection
from django.http import JsonResponse, StreamingHttpResponse
from django.utils import timezone
from django.utils.text import slugify
from django.core.exceptions import ObjectDoesNotExist

from rest_framework import viewsets, filters, renderers
from django.views.generic import DetailView, ListView, TemplateView
from rest_framework import filters, renderers, viewsets
from rest_framework.response import Response

from camp_fin.models import Transaction, Candidate, PAC, Entity, Lobbyist, Organization
from camp_fin.api_parts import (
TransactionSerializer,
TopMoneySerializer,
SearchCSVRenderer,
DataTablesPagination,
SearchCSVRenderer,
TopMoneySerializer,
TransactionCSVRenderer,
TransactionSerializer,
)

from camp_fin.models import PAC, Candidate, Entity, Lobbyist, Organization, Transaction
from pages.models import Page

TWENTY_TEN = timezone.make_aware(datetime(2010, 1, 1))
Expand Down
12 changes: 8 additions & 4 deletions camp_fin/context_processors.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
from django.conf import settings
from django.db import connection


def last_updated(request):
cursor = connection.cursor()

cursor.execute('''
cursor.execute(
"""
SELECT
MAX(received_date) AS last_updated
FROM camp_fin_transaction
WHERE received_date <= NOW()
''')
"""
)

last_updated = cursor.fetchone()[0]

return {'LAST_UPDATED': last_updated}
return {"LAST_UPDATED": last_updated}


def seo_context(request):

return {'SITE_META': settings.SITE_META}
return {"SITE_META": settings.SITE_META}
Loading
Loading