A Django-based web application for creating and managing approval voting polls. This platform provides an alternative to traditional plurality voting polls, allowing voters to approve of multiple options rather than being limited to a single choice.
The application can be used as a standalone service at vote.electionscience.org or the approval_polls package can be integrated into other Django projects.
- Approval Voting: Voters can approve of multiple options in a single poll
- Embeddable Polls: Polls can be embedded in other websites via iframe
- Multiple Voting Types: Public, authenticated, and invitation-only polls
- Real-time Results: View approval counts and proportional vote calculations
- User Management: User accounts with poll creation and management
- Tagging System: Organize polls with tags
- Email Integration: Optional email opt-in and invitation system
- Python 3.14.0 or higher
- UV package manager
- Git
git clone [email protected]:electionscience/vote.electionscience.org.git
cd vote.electionscience.orgCopy the example environment file and fill in the required values:
cp .env.dist .envEdit .env with your configuration. At minimum, you'll need to set:
DEBUG=Truefor local developmentSECRET_KEY(generate a random string)SENDGRID_API_KEY(optional, for email functionality)GOOGLE_SECRET(optional, for Google OAuth)
UV manages both Python versions and dependencies. It will automatically detect the required Python version from pyproject.toml (requires >=3.14.0) and .python-version (specifies 3.14).
Install UV:
# macOS/Linux
brew install uv
# Or use the official installer
curl -LsSf https://astral.sh/uv/install.sh | shInstall project dependencies:
uv syncThe uv sync command will:
- Automatically install Python 3.14 if needed
- Create a virtual environment (
.venv) - Install all dependencies from
pyproject.toml - Generate or update
uv.lockfor reproducible builds
Note: uv commands (like uv sync, uv run, uv pip install) automatically detect and use the .venv directory, so manual activation isn't required for uv commands. However, if you want to run python directly or use other tools like pytest or mypy, you'll need to activate the virtualenv:
source .venv/bin/activateOptional: Auto-activate virtualenv with direnv
For convenience, you can use direnv to automatically activate the virtualenv when entering this directory:
# Install direnv
brew install direnv
# Add to your shell (add this to ~/.zshrc)
eval "$(direnv hook zsh)"
# Create .envrc file in the project directory
echo 'export VIRTUAL_ENV="$PWD/.venv"' > .envrc
echo 'export PATH="$VIRTUAL_ENV/bin:$PATH"' >> .envrc
# Allow direnv in this directory (only needed once)
direnv allowThis will automatically activate .venv when you cd into the project directory and deactivate it when you leave.
Adding dependencies:
To add a new dependency, use:
uv add package-nameThis will update pyproject.toml and uv.lock automatically.
Run migrations to create the database tables:
python manage.py migrateDuring the first migration, you'll be prompted to create a superuser account. This is recommended for accessing the Django admin interface and creating polls.
Collect static files for the admin interface and other static assets:
python manage.py collectstatic --noinputIf you need email functionality to work correctly, update the site domain in the Django admin:
- Start the server:
python manage.py runserver - Visit
http://localhost:8000/admin - Go to Sites → Sites
- Change the domain from
example.comtolocalhost:8000(or your actual domain)
python manage.py runserverVisit http://localhost:8000/ in your browser.
You can now:
- Log in with your superuser account
- Create new polls
- Vote in polls
- View results
Run the test suite:
python manage.py testOr using pytest:
pytestThe project uses pytest with Django integration. Test files should be named test_*.py or *_tests.py.
We use Trunk to enforce consistent coding style:
npm install -g @trunk/cli
trunk checkThe project uses type hints. Run type checking with:
mypy approval_pollsapproval_polls/
├── models.py # Poll, Choice, Ballot, Vote models
├── views.py # View handlers for polls, voting, results
├── urls.py # URL routing
├── settings.py # Django configuration
├── templates/ # HTML templates
├── staticfiles/ # Static assets (CSS, JS, images)
└── tests.py # Test suite
This project is deployed to production on fly.io from an account managed by Felix Sargent.
Deployment process:
- Ensure you have the flyctl CLI installed
- Configure your fly.io app (see
fly.toml) - Deploy:
fly deployNote: Docker is only used for fly.io deployment via the Dockerfile. For local development, you run Django directly without Docker.
The Dockerfile uses UV to install dependencies and runs the application with gunicorn.
Automatic deployments: The project is configured to automatically deploy to production on push to the main branch.
We welcome contributions! Here are some resources to get started:
- Python: Google's Python tutorial
- Django: Django documentation (start with the tutorial)
- Git: Pro Git book
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
python manage.py test - Check code style:
trunk check - Submit a pull request
- Follow PEP 8 style guidelines
- Use type hints where appropriate
- Write tests for new features
- Update documentation as needed
- Run
trunk checkbefore submitting
See LICENSE file for details.
For issues, questions, or contributions, please open an issue on GitHub.
- Approval Voting - Learn more about approval voting
- The Center for Election Science - Organization behind this project