Django Visualizer

Subpackages

Admin

Admin page configuration

class visualizer.admin.HomepageFeaturedElectionAdmin(model, admin_site)

Bases: ModelAdmin

Administer homepage featured links

list_display = ('title', 'order', 'column', 'jsonConfig')
property media
raw_id_fields = ('jsonConfig',)
class visualizer.admin.HomepageFeaturedElectionColumnAdmin(model, admin_site)

Bases: ModelAdmin

Administer homepage featured link columns

list_display = ('title', 'order')
property media
class visualizer.admin.JsonAdmin(model, admin_site)

Bases: CursorPaginatorAdmin

The admin page to modify JsonConfig

actions = [<function make_movie>]
list_display = ('slug', 'title', 'owner', 'numRounds', 'numCandidates', 'uploadedAt', 'movieGenerationStatus')
property media
readonly_fields = ('slug', 'title', 'numRounds', 'numCandidates', 'uploadedAt', 'movieGenerationStatus')
search_fields = ['slug']
show_full_result_count = False
view_on_site = True
visualizer.admin.make_movie(_, request, queryset)

An action from the admin menu that creates a movie

Common

A set of common utilities to be used across modules

visualizer.common.candidate_renames()

A dictionary mapping how we should rename candidate names

visualizer.common.get_host(request)

Returns the HTTP_HOST, split for easy mocking

visualizer.common.intify(notint)

Turn into int if it’s a round number

visualizer.common.make_complete_url(request, urlWithoutDomain)

Returns the complete URL, including domain

visualizer.common.percentify(numerator, denominator)

Turn a float into a percentage string. Or, if the denominator is zero, returns an empty string

Forms

Forms enable users to create Models

class visualizer.forms.UploadByDataTableForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)

Bases: UploadForm

Used by the upload form using the DataTables entry

class Meta

Bases: Meta

Metadata is all we need here

fields = ['candidateSidecarFile', 'rotateNames', 'showRoundNumbersOnSankey', 'onlyShowWinnersTabular', 'doUseDescriptionInsteadOfTimeline', 'isPreferentialBlock', 'hideSankey', 'hideTabular', 'doDimPrevRoundColors', 'excludeFinalWinnerAndEliminatedCandidate', 'hideDecimals', 'colorTheme', 'eliminationBarColor', 'dataSourceURL', 'areResultsCertified', 'textForWinner']
base_fields = {'areResultsCertified': <django.forms.fields.BooleanField object>, 'candidateSidecarFile': <django.forms.fields.FileField object>, 'colorTheme': <django.forms.fields.IntegerField object>, 'dataSourceURL': <django.forms.fields.URLField object>, 'doDimPrevRoundColors': <django.forms.fields.BooleanField object>, 'doUseDescriptionInsteadOfTimeline': <django.forms.fields.BooleanField object>, 'eliminationBarColor': <django.forms.fields.IntegerField object>, 'excludeFinalWinnerAndEliminatedCandidate': <django.forms.fields.BooleanField object>, 'hideDecimals': <django.forms.fields.BooleanField object>, 'hideSankey': <django.forms.fields.BooleanField object>, 'hideTabular': <django.forms.fields.BooleanField object>, 'isPreferentialBlock': <django.forms.fields.BooleanField object>, 'jsonFile': <django.forms.fields.FileField object>, 'onlyShowWinnersTabular': <django.forms.fields.BooleanField object>, 'rotateNames': <django.forms.fields.BooleanField object>, 'showRoundNumbersOnSankey': <django.forms.fields.BooleanField object>, 'textForWinner': <django.forms.fields.IntegerField object>}
clean_jsonFile()

Converts the datatables json to URCVT json

declared_fields = {'colorTheme': <django.forms.fields.IntegerField object>, 'eliminationBarColor': <django.forms.fields.IntegerField object>, 'jsonFile': <django.forms.fields.FileField object>, 'textForWinner': <django.forms.fields.IntegerField object>}
property media

Return all media required to render the widgets on this form.

class visualizer.forms.UploadForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)

Bases: ModelForm

Used by the upload form

class Meta

Bases: object

Metadata is all we need here

fields = ['jsonFile', 'candidateSidecarFile', 'rotateNames', 'showRoundNumbersOnSankey', 'onlyShowWinnersTabular', 'doUseDescriptionInsteadOfTimeline', 'isPreferentialBlock', 'hideSankey', 'hideTabular', 'doDimPrevRoundColors', 'excludeFinalWinnerAndEliminatedCandidate', 'hideDecimals', 'colorTheme', 'eliminationBarColor', 'dataSourceURL', 'areResultsCertified', 'textForWinner']
model

alias of JsonConfig

base_fields = {'areResultsCertified': <django.forms.fields.BooleanField object>, 'candidateSidecarFile': <django.forms.fields.FileField object>, 'colorTheme': <django.forms.fields.IntegerField object>, 'dataSourceURL': <django.forms.fields.URLField object>, 'doDimPrevRoundColors': <django.forms.fields.BooleanField object>, 'doUseDescriptionInsteadOfTimeline': <django.forms.fields.BooleanField object>, 'eliminationBarColor': <django.forms.fields.IntegerField object>, 'excludeFinalWinnerAndEliminatedCandidate': <django.forms.fields.BooleanField object>, 'hideDecimals': <django.forms.fields.BooleanField object>, 'hideSankey': <django.forms.fields.BooleanField object>, 'hideTabular': <django.forms.fields.BooleanField object>, 'isPreferentialBlock': <django.forms.fields.BooleanField object>, 'jsonFile': <django.forms.fields.FileField object>, 'onlyShowWinnersTabular': <django.forms.fields.BooleanField object>, 'rotateNames': <django.forms.fields.BooleanField object>, 'showRoundNumbersOnSankey': <django.forms.fields.BooleanField object>, 'textForWinner': <django.forms.fields.IntegerField object>}
declared_fields = {'colorTheme': <django.forms.fields.IntegerField object>, 'eliminationBarColor': <django.forms.fields.IntegerField object>, 'textForWinner': <django.forms.fields.IntegerField object>}
property media

Return all media required to render the widgets on this form.

JS Utils

A helper function for javascript-generating python

visualizer.jsUtils.approx_length(stringToMeasure)

c/o https://stackoverflow.com/a/16008023/1057105 - measure the approximate pixels of the given string

Models

The django object models

class visualizer.models.ColorTheme(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntegerChoices

Describes the status of movie generation for this model

ALTERNATING = 2
PURPLE_TO_ORANGE = 1
RAINBOW = 0
class visualizer.models.EliminationBarColor(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntegerChoices

Describes the status of movie generation for this model

GRAY = 0
HIDDEN = 1
LAST_ROUND_COLOR = 2
class visualizer.models.HomepageFeaturedElection(*args, **kwargs)

Bases: Model

Represents a single link on the homepage list of featured elections.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

column

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

column_id
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

jsonConfig

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

jsonConfig_id
objects = <django.db.models.manager.Manager object>
order

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

title

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class visualizer.models.HomepageFeaturedElectionColumn(*args, **kwargs)

Bases: Model

Represents a column of links on the homepage.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

objects = <django.db.models.manager.Manager object>
order

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

title

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class visualizer.models.JsonConfig(*args, **kwargs)

Bases: Model

A Json file representing a single election, and its configuration

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

areResultsCertified

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

candidateSidecarFile

The descriptor for the file attribute on the model instance. Return a FieldFile when accessed so you can write code like:

>>> from myapp.models import MyModel
>>> instance = MyModel.objects.get(pk=1)
>>> instance.file.size

Assign a file object on assignment so you can do:

>>> with open('/path/to/hello.world') as f:
...     instance.file = File(f)
colorTheme

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

dataSourceURL

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

detail_views = ('visualizer.views.Visualize',)
doDimPrevRoundColors

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

doUseDescriptionInsteadOfTimeline

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

electionpage_set

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

eliminationBarColor

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

excludeFinalWinnerAndEliminatedCandidate

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_absolute_url()

Used in the admin panel to have a “Visit Site” link

classmethod get_all_non_auto_fields()

All editable fields of JsonConfig - must be kept up to date with the list of fields above. (I’m sure there’s a way to do this automatically…)

classmethod get_all_public()

Returns users whose data can be included in sitemap & index

get_colorTheme_display(*, field=<django.db.models.fields.IntegerField: colorTheme>)
get_eliminationBarColor_display(*, field=<django.db.models.fields.IntegerField: eliminationBarColor>)
get_movieGenerationStatus_display(*, field=<django.db.models.fields.IntegerField: movieGenerationStatus>)
get_next_by_uploadedAt(*, field=<django.db.models.fields.DateTimeField: uploadedAt>, is_next=True, **kwargs)
get_previous_by_uploadedAt(*, field=<django.db.models.fields.DateTimeField: uploadedAt>, is_next=False, **kwargs)
get_textForWinner_display(*, field=<django.db.models.fields.IntegerField: textForWinner>)
hideDecimals

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

hideSankey

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

hideTabular

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

isPreferentialBlock

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

jsonFile

The descriptor for the file attribute on the model instance. Return a FieldFile when accessed so you can write code like:

>>> from myapp.models import MyModel
>>> instance = MyModel.objects.get(pk=1)
>>> instance.file.size

Assign a file object on assignment so you can do:

>>> with open('/path/to/hello.world') as f:
...     instance.file = File(f)
movieGenerationStatus

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

movieHorizontal

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

movieHorizontal_id
movieVertical

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

movieVertical_id
multiscraper

Accessor to the related object on the reverse side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

numCandidates

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

numRounds

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
onlyShowWinnersTabular

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

owner

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

owner_id
rawDownloadedBy

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

rotateNames

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

save(*args, **kwargs)

Save the current instance. Override this in a subclass if you want to control the saving process.

The ‘force_insert’ and ‘force_update’ parameters can be used to insist that the “save” must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set.

scraper

Accessor to the related object on the reverse side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

showRoundNumbersOnSankey

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

slug

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

textForWinner

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

title

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

uploadedAt

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class visualizer.models.MovieGenerationStatuses(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntegerChoices

Describes the status of movie generation for this model

COMPLETE = 4
FAILED = 5
LANDSCAPE_COMPLETE = 3
NOT_REQUESTED = 0
NOT_STARTED = 1
PICKED_UP_BY_TASK = 2
class visualizer.models.TextForWinner(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntegerChoices

Describes the status of movie generation for this model

ELECTED = 0
LEAD = 3
PRIMARY = 2
WON = 1

Template Tags

Helper functions for reversing and getting absolute URLs, including the domain

visualizer.templatetags.reverse.get_as_complete_url(context, url)

Takes a URL and returns the full URL, including domain, if it’s not already

visualizer.templatetags.reverse.get_reverse_as_complete_url(context, name, *args)

Runs reverse and then returns the full URL, including domain

Tag to get a share icon, to be used in tandem with django_social_share

visualizer.templatetags.share_icon.get_icon(shareTo)

Pass in the text label. Will return an image from /share_icons/ of the same name.

Tests

URLs

URLs for the primary upload and visualization app

Views

The django views file

class visualizer.views.BallotpediaViewSet(*args, **kwargs)

Bases: LoggingMixin, ModelViewSet

API endpoint with all ballotpedia fields

basename = None
description = None
detail = None
name = None
perform_create(serializer)
permission_classes = [<class 'accounts.permissions.HasAPIAccess'>, <class 'accounts.permissions.IsOwnerOrReadOnly'>]
queryset
serializer_class

alias of BallotpediaSerializer

suffix = None
class visualizer.views.DownloadRawData(**kwargs)

Bases: LoginRequiredMixin, DetailView

Download raw data - don’t just share the presigned AWS URL, we want a fresh URL for each download.

get_context_data(**kwargs)

Insert the single object into the context dict.

login_url = 'login'
model

alias of JsonConfig

redirect_field_name = 'redirect_to'
template_name = 'visualizer/rawdata.html'
class visualizer.views.Index(**kwargs)

Bases: TemplateView

The homepage

build_path = 'index.html'
get_context_data(**kwargs)
template_name = 'visualizer/index.html'
class visualizer.views.JsonOnlyViewSet(*args, **kwargs)

Bases: LoggingMixin, ModelViewSet

API endpoint that allows tabulated JSONs to be viewed or edited.

basename = None
description = None
detail = None
name = None
perform_create(serializer)
permission_classes = [<class 'accounts.permissions.HasAPIAccess'>, <class 'accounts.permissions.IsOwnerOrReadOnly'>]
queryset
serializer_class

alias of JsonOnlySerializer

suffix = None
class visualizer.views.Oembed(**kwargs)

Bases: View

The oembed protocol, pointing to VisualizeEmbedded

dispatch(request, *args, **kwargs)
get(request)

Overriding the getter for this class-based view

class visualizer.views.Upload(**kwargs)

Bases: LoginRequiredMixin, CreateView

The upload page

build_path = 'upload.html'
form_class

alias of UploadForm

form_invalid(form)

If the form is invalid, render the invalid form.

form_valid(form)

If the form is valid, save the associated model.

include = ['jsonFile', 'candidateSidecarFile', 'rotateNames', 'showRoundNumbersOnSankey', 'onlyShowWinnersTabular', 'doUseDescriptionInsteadOfTimeline', 'isPreferentialBlock', 'hideSankey', 'hideTabular', 'doDimPrevRoundColors', 'excludeFinalWinnerAndEliminatedCandidate', 'hideDecimals', 'colorTheme', 'eliminationBarColor', 'dataSourceURL', 'areResultsCertified', 'textForWinner']
login_url = 'login'
model

alias of JsonConfig

redirect_field_name = 'redirect_to'
success_url = 'v/{slug}'
template_name = 'visualizer/uploadFile.html'
class visualizer.views.UploadByDataTable(**kwargs)

Bases: Upload

Upload form when using the datatables input

form_class

alias of UploadByDataTableForm

class visualizer.views.UserViewSet(*args, **kwargs)

Bases: LoggingMixin, ReadOnlyModelViewSet

API endpoint that allows you to view but not edit Users.

basename = None
description = None
detail = None
name = None
permission_classes = [<class 'rest_framework.permissions.IsAdminUser'>]
queryset
serializer_class

alias of UserSerializer

suffix = None
class visualizer.views.ValidateDataEntry(**kwargs)

Bases: LoginRequiredMixin, View

Validation AJAX view: would the current input succeed in creating a graph?

post(request)

Doesn’t render a webpage - just text

class visualizer.views.Visualize(**kwargs)

Bases: DetailView

Visualizing a single JsonConfig

get(request, *args, **kwargs)
get_context_data(**kwargs)

Insert the single object into the context dict.

model

alias of JsonConfig

template_name = 'visualizer/visualize.html'
class visualizer.views.VisualizeBallotpedia(**kwargs)

Bases: DetailView

The embedded ballotpedia visualization

dispatch(request, *args, **kwargs)
get(request, *args, **kwargs)
get_context_data(**kwargs)

Insert the single object into the context dict.

model

alias of JsonConfig

template_name = 'visualizer/visualize-ballotpedia.html'
class visualizer.views.VisualizeEmbedded(**kwargs)

Bases: DetailView

The embedded visualization, to be used in an iframe.

dispatch(request, *args, **kwargs)
get(request, *args, **kwargs)
get_context_data(**kwargs)

Insert the single object into the context dict.

model

alias of JsonConfig

template_name = 'visualizer/visualize-embedded.html'
class visualizer.views.VisualizeEmbedly(**kwargs)

Bases: RedirectView

VisualizeEmbedded, but without any custom arguments so it can be supported by embedly. Since embedly doesn’t allow custom arguments, we cannot use ?vistype in oembed. We have replaced this with /vo/slug/vistype instead,

Further, we simplify vistype so it reads more easily. The changed vistypes are: barchart-interactive –> bar barchart-fixed –> bar-static tabular-candidate-by-round –> table tabular-by-round-interactive –> table-by-round tabular-by-round –> table-by-round-static tabular-by-candidate –> table-by-candidate

get_redirect_url(*args, **kwargs)

Return the URL redirect to. Keyword arguments from the URL pattern match generating the redirect request are provided as kwargs to this method.

pattern_name = 'visualizeEmbedded'
permanent = True