# Parsifal turns the screening stage of a systematic review into a database task

> Parsifal is a Django application for researchers running systematic literature reviews, covering the search, filtering, inclusion and exclusion of primary studies, with an importer that pulls records from databases such as Elsevier. It runs on Django 4.1 and PostgreSQL 12, with SQLite for local work.

**vitorfs/parsifal** — Parsifal is a tool to assist researchers to perform Systematic Literature Reviews

- Repository: https://github.com/vitorfs/parsifal
- Website: https://parsif.al
- Stars: 527 · Forks: 188
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/vitorfs-parsifal

## The problem it solves, stated as a research workflow

The README's About section is the clearest statement of the problem, and it borrows a definition directly from the literature. A systematic literature review is a secondary study with the objective to identify, analyze and interpret all available evidence from primary studies related to a specific research question. As suggested by Kitchenham and Charters, the activity to perform a systematic literature review involves planning, conducting, and reporting the review.

Then the part that explains why a piece of software exists at all. Performing a systematic literature review is a labor-intensive task that requires a huge amount of work from the researcher: designing the protocol, adjusting the search string, filtering the results, sometimes more than a thousand articles, selecting those articles that attend the inclusion criteria, and removing those articles that attend the exclude criteria. After that, the researcher might start to analyze the relevant result one by one.

That enumeration is the workflow Parsifal is built around. Protocol design and reporting are human activities, but the middle of the list is data processing, and data processing done in a spreadsheet is where systematic reviews go wrong. A thousand rows of citations with decisions in a cell, filters that cannot be combined, and no record of who excluded what or when.

Turning each article into a record with an inclusion status turns screening into a query. You can ask how many records remain under a given inclusion criterion, how many were excluded and by whom, and which ones are duplicated across searches. That is the same reason systematic reviews insist on a protocol in the first place, expressed in software.

The tool is described as a tool to support researchers to perform systematic literature reviews, and the homepage is parsif.al. The primary language is Python, the licence is MIT, and the default branch is dev rather than master, which is worth noting because it means the development branch is the one where work happens. The last push was on 2026-05-05.

## The stack is deliberately conservative, and that is a decision

The Tech Stack section lists the versions the project is currently running on, and each one tells you something about the project's priorities.

Python 3.9, Django 4.1, PostgreSQL 12, Bootstrap 3.4 and jQuery 3.6.

PostgreSQL is the interesting one, because for a research tool PostgreSQL 12 is old but it is also a serious relational database with proper full-text search, transactions and concurrent access. A review with a dozen researchers screening at the same time needs real concurrency, and a screening queue with tens of thousands of records needs an index that will not fall over. SQLite would not serve that, which is why SQLite appears in the local setup instructions rather than in the stack.

Bootstrap 3.4 and jQuery 3.6 are the opposite kind of choice. They are the versions a Django project of that generation shipped with, and they are unremarkable rather than aspirational. For a research tool, the frontend is a set of forms and tables, and a stable old CSS framework with a stable old JavaScript library is a defensible way to avoid a dependency chain you have to maintain for the life of a PhD.

The frontend choice also fits the interface. The work happens in tables and forms, not in a rich application, and the frontend stack here is what Django's own admin and generic form views work with.

The pyproject.toml shows the tooling behind it. Black is configured with a line length of 119 and target versions from py36 through py39, which is consistent with the stated Python 3.9, and the project carries a code style badge for Black. Towncrier is configured with the package name parsifal and the filename CHANGELOG.md, so the changelog at the repository root is generated from news fragments rather than written by hand, which is the convention for keeping a long-running project's history consistent.

## Setting up locally, and the database choice you make first

The local setup instructions are complete and worth following in order, because each step depends on the last.

Clone the repository:

```bash
git clone https://github.com/vitorfs/parsifal.git
```

Create a virtualenv and activate it:

```bash
python3 -m venv venv
```

```bash
source venv/bin/activate
```

Then install the development requirements:

```bash
pip install -r requirements/local.txt
```

The requirements/ directory at the repository root is split, with local.txt being the development set, so a production install is a different file.

Then the database, and this is the step where the README offers you a choice. You should either set up a local PostgreSQL database or use SQLite, and the configuration is a .env file in the project root that you make by copying .env.example:

```bash
cp .env.example .env
```

For PostgreSQL, you add the DATABASE_URL with the connection string pointing at your local database:

```bash
DATABASE_URL=postgres://richardwagner:holygrail@localhost:5432/parsifal
```

For SQLite, the URL uses a four-slash form because the path is absolute:

```bash
DATABASE_URL=sqlite:////tmp/parsifal.sqlite3
```

and the same form with a fuller path puts the file somewhere else:

```bash
DATABASE_URL=sqlite:////Users/vitor/dev/parsifal/parsifal.sqlite3
```

Then the migrations and the server:

```bash
python manage.py migrate
```

```bash
python manage.py runserver
```

and a super user to log in with:

```bash
python manage.py createsuperuser
```

The order matters in one place: the migrations have to run before the server, and the super user before you can log in, and neither works until the DATABASE_URL points at a database that exists.

The .env.example also shows the rest of the configuration. DEBUG is on, there is a SECRET_KEY, ALLOWED_HOSTS is wide open, and the email settings use Django's file-based email backend with EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD and EMAIL_USE_TLS. That last detail is not incidental: a review tool sends invitations and notifications to researchers by email, so the mail configuration is a real part of running it rather than an afterthought.

And there is ELSEVIER_API_KEY=api_key, which is the import path. The key is what lets the tool pull records from Elsevier's bibliographic databases.

## Where Parsifal is the wrong tool

Three limits, and the first is about who the tool is for.

The first is that Parsifal is a group tool, not a personal one. The workflow it assumes is the one where a search returns more than a thousand articles and several people have to agree on which ones to include. A researcher doing a narrative review, or a systematic review of twenty papers, does not need a database, a migration step and a super user; they need a document manager and an hour.

The second is the age of the stack. The project states it runs on Python 3.9 with Django 4.1 and PostgreSQL 12. Django 4.1 was released in the middle of 2023, and the versions have moved several times since. That is not a blocker, because Django applications are usually upgradeable a minor version at a time, but it is work. The Bootstrap 3.4 and jQuery 3.6 pairing is dated in a more permanent way, since those versions are effectively frozen.

The third is that the release history is uneven. The recent releases are v2.2.1 from 2026-02-08, v2.2.0 from 2022-08-14 and v2.1.1 from 2021-09-29. So there is a long gap between the 2.2.0 release in 2022 and the 2.2.1 in 2026, with the work continuing in between on the dev branch.

That gap is also a signal about the project's shape. A tool used by a research group is deployed once, by one person, and then kept running for the duration of a PhD or a grant. It does not need a release cadence, and the absence of one is not the same as neglect, especially with a CHANGELOG.md generated by towncrier and a SECURITY.md present in the repository.

The alternative approach for a research group that does not want to run a server is a reference manager with a plugin, or a structured approach kept in a spreadsheet with a documented protocol. The difference in approach is that Parsifal gives you queryable screening decisions and a shared database, and it costs you a Django deployment, an import pipeline configured per bibliographic source, and the responsibility of maintaining it. For a review with a dozen researchers and a deadline, the database is worth it. For one person with a short list, it is a system to maintain rather than a tool to use.

## The Makefile, the security file and the shape of the repository

The top-level entries and the small amount of configuration in the tree tell you how the project is put together and how it is maintained.

The Makefile is short and its build target is a lint-and-check pipeline rather than a packaging one:

```
build:
	isort parsifal
	black parsifal
	flake8 parsifal
	./manage.py makemigrations --check --dry-run --settings=parsifal.settings.tests
```

Four steps. isort and black normalise the import order and the formatting, flake8 does the linting, and the last step is the interesting one. The makemigrations check with the dry-run flag and the test settings verifies that the models have no uncommitted migration pending, which is the standard way to catch a developer who edited a model and forgot to generate the migration.

The settings module named there, parsifal.settings.tests, tells you the layout. The parsifal/ directory at the repository root is the Django project, with the settings, the models and the views inside it, and the settings are split so that a test-specific settings module exists alongside the production one. That is a conventional arrangement and the presence of the check means the project enforces the convention.

The pyproject.toml confirms the towncrier setup, with the package name parsifal and the filename CHANGELOG.md, and the presence of a CHANGELOG.md at the root plus a SECURITY.md and a CONTRIBUTING.md is the standard set for a project with outside users.

The other entries are the development scaffolding: tox.ini for running the test suite in environments, setup.cfg alongside the pyproject, a Makefile, an etc/ directory, a bin/ directory, manage.py, requirements/ split into multiple files, and .editorconfig for whitespace. The default branch is dev, which tells you that the README's instructions, which mention the master branch in a couple of links, are at least a version behind the development branch.

There is also a .env.example checked into the repository, with a DEBUG flag set to true, a placeholder SECRET_KEY, a wide-open ALLOWED_HOSTS value, the file-based email backend, and the Elsevier API key. Checking that file in is the right practice for a project that needs a dozen settings, because it makes the required configuration discoverable, but it also means the defaults are development defaults. A deployment that copies .env.example without changing ALLOWED_HOSTS or generating a real SECRET_KEY is running a research tool with a published secret key, which matters if the instance is reachable.

## Conclusion

Adopt Parsifal if your research group runs systematic literature reviews and is tracking thousands of candidate papers in a spreadsheet, because the screening, inclusion and exclusion decisions become queryable records rather than rows you re-sort every week. Do not adopt it for a single reviewer or a handful of papers, because the setup is a Django server with a database, an Elsevier API key and an import step. Verify first that the Python, Django and PostgreSQL versions in the tech stack section match what you are deploying, since the project states it runs on Python 3.9 with Django 4.1 and PostgreSQL 12, and that you have the API key for whichever bibliographic source you intend to import from, since the .env.example shows the import path is configured through environment variables.

## FAQ

### What is Parsifal used for?

It supports researchers performing systematic literature reviews, covering the labour-intensive middle of that work: designing the protocol, adjusting the search string, filtering results that may run to more than a thousand articles, selecting those that meet the inclusion criteria and removing those that meet the exclusion criteria.

### What technology stack does Parsifal run on?

The project states it runs on Python 3.9, Django 4.1, PostgreSQL 12, Bootstrap 3.4 and jQuery 3.6, and it is MIT licensed with the source released under that licence.

### How do I run Parsifal locally?

Clone the repository, create a virtualenv with python3 -m venv venv, activate it, install requirements/local.txt with pip, copy .env.example to .env, set DATABASE_URL, then run python manage.py migrate, python manage.py runserver and python manage.py createsuperuser.

### Can Parsifal use SQLite instead of PostgreSQL?

Yes. The README says you should either set up a local PostgreSQL database or use SQLite, and gives the SQLite form of DATABASE_URL as sqlite:////tmp/parsifal.sqlite3 for a temporary file or an absolute path for a permanent one.

### What does the Parsifal .env file need to contain?

Besides DEBUG, SECRET_KEY, ALLOWED_HOSTS and DATABASE_URL, the example sets the email backend and its host, port, credentials and TLS flag, plus an ELSEVIER_API_KEY that the import path uses. The email settings are needed because the tool sends notifications to researchers.

### How is the Parsifal changelog maintained?

Towncrier is configured in pyproject.toml with the package name parsifal and the filename CHANGELOG.md, so the changelog is generated from news fragments rather than written by hand. The project also uses Black with a line length of 119 and a flake8 and isort pass in the Makefile build target.

## Sources

- [License: MIT](https://github.com/vitorfs/parsifal/blob/dev/LICENSE)
- [Project website](https://parsif.al)
- [README](https://github.com/vitorfs/parsifal/blob/dev/README.md)
- [Releases](https://github.com/vitorfs/parsifal/releases)
- [vitorfs/parsifal on GitHub](https://github.com/vitorfs/parsifal)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vitorfs-parsifal
