Ekratia’s documentation!¶
Ekratia is a new way of making democracy. Members of Ekratia use the Internet to vote directly for new ideas and laws. In case they are too busy to vote, members can delegate their vote to other members. Members can change their delegates on real time.
Contents:
Installation¶
Clone the Ekratia
repository:
$ git clone git@github.com:ekratia/ekratia.git
This project was created using cookiecutterdjango_
Setup project locally¶
The steps below will get you up and running with a local development environment. We assume you have the following installed:
- pip
- virtualenv
- PostgreSQL
First make sure to create and activate a virtualenv, then open a terminal at the project root and install the os dependencies:
$ sudo ./install_os_dependencies.sh install
Then install the requirements for your local development:
$ pip install -r requirements/local.txt
Then, create a PostgreSQL database with the following command. We will call the
database ekratia
$ createdb ekratia
You can now run the usual Django migrate
and runserver
command:
$ python manage.py migrate
$ python manage.py runserver
Live reloading and Sass CSS compilation
If you’d like to take advantage of live reloading and Sass / Compass CSS compilation you can do so with the included Grunt task.
Make sure that nodejs is installed. Then in the project root run:
$ npm install
Now you just need:
$ grunt serve
The base app will now run as it would with the usual manage.py runserver
but with live reloading and Sass compilation enabled.
To get live reloading to work you’ll probably need to install an appropriate browser extension
Run Unit Tests¶
python manage.py test
Front-end Application¶
We use bower to manage the Front-end dependencies. The project already has a compiled and minified version of the dependencies. So you only need to run it when adding new dependencies.
npm -g install bower
bower install
Path of front-end libraries: /bower_components
API¶
API endpoints used in the Ekratia
application to be consumed inside the application.
The endpoints are located inside /api/v1/<endpoint>
Users¶
-
class
ekratia.users.api.
UserView
(**kwargs)¶ API User details Endpoint
-
model
¶ alias of
User
-
serializer_class
¶ alias of
UserSerializer
-
-
class
ekratia.users.serializers.
UserSerializer
(instance=None, data=<class rest_framework.fields.empty>, **kwargs)¶ Serializer for User Model
Conversations¶
Delegates¶
-
class
ekratia.delegates.api.
AssignedDelegates
(**kwargs)¶ API class for User Delegates
-
model
¶ alias of
User
-
serializer_class
¶ alias of
UserSerializer
-
Referendums¶
-
class
ekratia.referendums.api.
ReferendumComments
(**kwargs)¶ List Comments of the referendum in a Tree
-
create_root_comment
(referendum)¶ Creates a root Comment
-
get
(request, pk, format=None)¶ Lists the tree of comments for the thread
-
get_referendum
(pk)¶ Get Referendum by Primary Key
-
update_information_from_tree
(tree)¶ Recursive function to go through tree and update information Updating: User information, Vote value
-
Graphs¶
Ekratia uses Networkx library to operate with graphs. GraphEkratia is a class that extends from DiGraph and implements required methods for the Ekratia vote system.
-
class
ekratia.core.graphs.
GraphEkratia
(*args, **kwargs)¶ Extends Digraph Class to add methods used in the voting system.
How to use it:
graph = GraphEkratia() graph.add_user_id(1) graph.add_users_ids([1,2,3])
-
add_user_id
(user_id)¶ Add a nodes from user_id
Param: user_id User Id.
-
add_users_ids
(users_ids)¶ Adds nodes to the graph from a list of user ids
Param: list users_ids: List of user ids
-
attach_predecessors
(node)¶ Attach the predecessors of a node
Param: node Id.
-
attach_succesors
(node)¶ Attach the succesors of a node
Param: node Id.
-
get_pagerank_values
()¶ dictionary of pagerank values for the nodes of the graph
Param: user_id User Id. Returns: pagerank calculation Return type: dict
-
get_sigma_representation
()¶ Representation for Sigma JS library
Returns: dict of nodes and edges Return type: dict
-
get_user_id_delegates
(user_id)¶ returns a list of ids of succesors of the node
Param: user_id User Id. Returns: list of user ids Return type: list
-
get_user_id_delegates_to_me
(user_id)¶ returns a list of ids of predecessors of the node
Param: user_id User Id. Returns: list of user ids Return type: list
-
queue_node
(node)¶ Queue a node for future revision
Param: node Id.
-
retrieve_node
()¶ Retrieves a node from the queue
Returns: node Return type: int
-
set_exclude_list
(users_ids)¶ Excludes list of ids from the Graph
Parameters: users_ids (list) – List of users ids
-
visit_node
(node)¶ Add a nodes to visited list
Param: node Id.
Users¶
Application in charge to handle all the information and methods of the users.
Models¶
-
class
ekratia.users.models.
User
(id, password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined, rank)¶ -
delegate_to
(user)¶ Creates a delegated user Return the Delegate object
-
get_available_delegates
(name=None)¶ Get users not delegated by me and exclude myself @param name: Filters available users by name
-
get_avatar
¶ Gets avatar from Django Avatar or Facebook
-
get_data_dictionary
()¶ Return dictionary with basic information of the user
-
get_full_name_or_username
¶ Get Full Name or Username
-
get_graph
()¶ Creates a graph for the user based on Delegation
-
get_users_delegated_by_me
()¶ Returns users delegated by me
-
get_users_delegated_to_me
()¶ Returns users that delegated me
-
get_vote_referendum
(referendum)¶ Return the value vote on a referendum if exists
-
undelegate_to
(user)¶ Undelegate an user Returns True if success
-
vote_count_for_referendum
(referendum)¶ Calculates vote value depending on Delegates
-
Referendums¶
Models¶
-
class
ekratia.referendums.models.
Referendum
(*args, **kwargs)¶ Entity that refers to a proposal made by an user to modify the rules. It is opened for vote for a period of time and the members vote to approve it or not.
-
approved
= None¶ True If approved, False if not approved, None not set yet
-
calculate_votes
()¶ Calculates total votes based on ReferendumUserVote
-
check_status
()¶ Method used to update status when necessary
-
comment
¶ Comment thread
-
comment_points
= None¶ Rating due to the comments, used to establish trendy referendums
-
count_comments
()¶ Counts the comments of the referendunm, updates the value and returns the count.
Returns: count of comments Return type: int
-
date
= None¶ Date of creation
-
get_count_votes
()¶ Calculates total votes for referenudm
-
get_graph
()¶ Get graph of the referendum
Returns: Graph of the referendum Return type: ekratia.core.graphs.GraphEkratia
-
get_num_negative_votes
()¶ Return the total negative votes
-
get_num_positive_votes
()¶ Returns total positive votes
-
get_total_votes
()¶ Calculates total votes for referenudm
-
get_total_votes_absolute
()¶ Returns Total ov votes for the referendum
-
is_approved
()¶ Get partial results and determines if It’s approved or not
Returns: True or False Return type: boolean
-
is_finished
()¶ Method to establish id Referendum is open for vote.
Returns: True or False Return type: boolean
-
is_open
()¶ Method to establish id Referendum is open for vote.
Returns: True or False Return type: boolean
-
num_comments
= None¶ Number of comments
-
open_remaining_time
()¶ Returns the remaining time for vote.
Returns: Remianing time for referendum to finish Return type: datetime.timedelta()
-
open_time
= None¶ Open Time of Referendum
-
points
= None¶ Total Value of the Referndum
-
slug
= None¶ Slugify version of the title
-
status
= None¶ Status options: created, open, finished
-
text_add_rules
= None¶ Text that will add to rules
-
text_remove_rules
= None¶ Rules that will remove from rules
-
title
= None¶ Title of the referendum
-
total_yes
= None¶ Total Values for Stats
-
update_totals
()¶ Update totals in the Database Returns the updated referendum
-
user
¶ User who created referendum
-
vote_process
(user, value)¶ Processes a vote for the referendum
Param: user User object Param: value Vote value (-1 or 1)
-
Views¶
-
class
ekratia.referendums.views.
ReferendumArchivedListView
(**kwargs)¶ List of Referendums
-
model
¶ alias of
Referendum
-
-
class
ekratia.referendums.views.
ReferendumCreateView
(**kwargs)¶ Creates a Referendum
-
form_class
¶ alias of
ReferendumForm
-
form_valid
(form)¶ If the form is valid, save the associated model.
-
model
¶ alias of
Referendum
-
-
class
ekratia.referendums.views.
ReferendumDetailView
(**kwargs)¶ Detail View for a Referendum
-
get_context_data
(**kwargs)¶ Insert the single object into the context dict.
-
model
¶ alias of
Referendum
-
-
class
ekratia.referendums.views.
ReferendumListView
(**kwargs)¶ List of Referendums
-
class
ekratia.referendums.views.
ReferendumOpenView
(*args, **kwargs)¶ Open Referendum and redirects back to Referendum
-
class
ekratia.referendums.views.
ReferendumProcessVoteView
(*args, **kwargs)¶ Process refrendum vote and redirects back to Referendum
Conversations¶
Models¶
-
class
ekratia.threads.models.
Comment
(*args, **kwargs)¶ Comment Model: Comments under Threads and other comments
-
calculate_votes
()¶ Calculates total votes based on CommentUserVote
-
-
class
ekratia.threads.models.
CommentManager
¶ Manager for the comment model. Allows custom operation on the tree.
-
class
ekratia.threads.models.
CommentUserVote
(*args, **kwargs)¶ CommentUserVote Model: Stores votes from users to Comments
Views¶
-
class
ekratia.conversations.views.
ThreadCreateView
(**kwargs)¶ Creates a Thread
-
form_class
¶ alias of
ThreadForm
-
form_valid
(form)¶ If the form is valid, save the associated model.
-
model
¶ alias of
Thread
-
Settings¶
This project relies extensively on environment settings which will not work with Apache/mod_wsgi setups. It has been deployed successfully with both Gunicorn/Nginx and even uWSGI/Nginx.
For configuration purposes, the following table maps environment variables to their Django setting:
Environment Variable | Django Setting | Development Default | Production Default |
---|---|---|---|
DJANGO_ADMIN_URL | n/a | r’^admin/’ | raises error |
DJANGO_CACHES | CACHES (default) | locmem | redis |
DJANGO_DATABASES | DATABASES (default) | See code | See code |
DJANGO_DEBUG | DEBUG | True | False |
DJANGO_SECRET_KEY | SECRET_KEY | CHANGEME!!! | raises error |
DJANGO_SECURE_BROWSER_XSS_FILTER | SECURE_BROWSER_XSS_FILTER | n/a | True |
DJANGO_SECURE_SSL_REDIRECT | SECURE_SSL_REDIRECT | n/a | True |
DJANGO_SECURE_CONTENT_TYPE_NOSNIFF | SECURE_CONTENT_TYPE_NOSNIFF | n/a | True |
DJANGO_SECURE_FRAME_DENY | SECURE_FRAME_DENY | n/a | True |
DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS | HSTS_INCLUDE_SUBDOMAINS | n/a | True |
DJANGO_SESSION_COOKIE_HTTPONLY | SESSION_COOKIE_HTTPONLY | n/a | True |
DJANGO_SESSION_COOKIE_SECURE | SESSION_COOKIE_SECURE | n/a | False |
DJANGO_DEFAULT_FROM_EMAIL | DEFAULT_FROM_EMAIL | n/a | “your_project_name <noreply@your_domain_name>” |
DJANGO_SERVER_EMAIL | SERVER_EMAIL | n/a | “your_project_name <noreply@your_domain_name>” |
DJANGO_EMAIL_SUBJECT_PREFIX | EMAIL_SUBJECT_PREFIX | n/a | “[your_project_name] “ |
DJANGO_ALLOWED_HOSTS | ALLOWED_HOSTS | [‘*’] | [‘your_domain_name’] |
Deployment¶
This project relies on Environment variables.
Please make sure you define the variables according to the Settings page:
Deployment to Production on AWS¶
System requirements for Debian based servers: requirements.apt
Python requirements: requirements.txt
It was succesfully tested and mounted on AWS using Python Virtualenv, UWSGI and NGINX.
UWSGI Configuration¶
[uwsgi]
vhost = true
plugins = python
socket = /tmp/ekratia.sock
master = true
enable-threads = true
processes = 4
wsgi-file = /srv/apps/ekratia/config/wsgi.py
virtualenv = /home/ubuntu/.virtualenvs/env
chdir = /srv/apps/ekratia/
Nginx Configuration¶
server {
listen 80;
access_log /var/log/nginx/ekratia.access.log;
error_log /var/log/nginx/ekratia.error.log;
location / {
uwsgi_pass unix:///tmp/ekratia.sock;
include uwsgi_params;
}
}
The used services were:
Amazon EC2
Amazon RDS PostgresSQL
Amazon S3