Repository name: omnipath-server-django
Minimum Viable Product (MVP):
- Load a subset of the interactions table (100 rows) into a PosgreSQL database.
- Build an API to retrieve information from this database.
- Python: >= 3.10
- Poetry
- Docker
- PosgreSQL: >=15
- pgAdmin or dBeaver
- Postman
- Configure Poetry environment to be created inside of project's folder
poetry config virtualenvs.in-project true- Create an empty project using Poetry
- Poetry ~1.8
poetry new omnipath-server-django- Poetry >2.0
poetry new omnipath-server-django --flat- Install Django Framework
The current version of Django by the time of writing this document is 5.1.6. We are going to install this version by using poetry add.
poetry add Django="5.1.6"- Install Django REST Framework
poetry add djangorestframework="^3.15"- Install CORS headers support for Django
poetry add django-cors-headers="^4.7.0"- Install Psycopg (PostgreSQL driver for Python)
# Psycopg 3 (recommended for new projects)
poetry add psycopg[binary]- Go to the root of the recently created project.
cd omnipath-server-django- Delete the folder
omnipath_server_django. This folder was created by Poetry. By doing this we are avoiding a possible conflict with the folder that Django will create.
rm -rf omnipath_server_django- Create an empty Django project (main project)
Note: do no forget the dot (.) at the end, this allows Django to create the project in the current folder
poetry run django-admin startproject omnipath_server_django .In the end of this process, you should check that the folder omnipath_server_django and a Python file have been created. The structure of the project should look like this:
omnipath-server-django/
├── manage.py # Django CLI tool
├── omnipath_server_django/ # Django project settings
│ ├── asgi.py # ASGI entry point
│ ├── __init__.py # init file│
│ ├── settings.py # project settings
│ ├── urls.py # root URL config
│ └── wsgi.py # WSGI entry point
├── poetry.lock # poetry lock file
├── pyproject.toml # poetry dependencies
├── README.md # project documentation
├── tests # test suite folder (unit, integration, etc.)
| └── __init__.py # init file
└── .venv/ # virtual environment (optional)- By default Django uses SQLite, for our project we are going to configure PosgreSQL as the default database. Open the
omnipath_server_django/settings.pyfile and add the following parameters in theDATABASESsection:
- Connection details:
- Database name:
omnipath_db - User:
postgres - Password:
omnipath_admin_123(for the superuserpostgres) - Host: 127.0.0.1 (localhost)
- Port: 5432 (default for PostgreSQL)
- Database name:
DATABASES = {
# ---------------------------
# -- PostgreSQL Settings --
# ---------------------------
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "omnipath_db",
"USER": "postgres",
"PASSWORD": "omnipath_admin_123",
"HOST": "127.0.0.1",
"PORT": 5432,
}
# --------------------------
# -- SQLite Settings --
# --------------------------
# "default": {
# "ENGINE": "django.db.backends.sqlite3",
# "NAME": BASE_DIR / "db.sqlite3",
# }
}- Create a Django app as part of the overall project, this app will be our API.
poetry run python startapp api- Register the following apps including the
apias part of the project in the fileomnipath_server_django/settings.py. Add the following elements inINSTALLED_APPSlist:
- "django.contrib.postgres"
- "rest_framework"
- "corsheaders"
- "api"
The INSTALLED_APPS should look like this:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.postgres",
"rest_framework",
"corsheaders",
"api",
]- Add the CORS middleware in the
MIDDLEWAREsection by adding the following:
- "corsheaders.middleware.CorsMiddleware"
The MIDDLEWARE section should look like this:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]A model is a class that represents a table or collection in a database. Our naming convention for tables will be the following:
- Use only lowercase letters and underscore to separate words.
- Add the suffix
omnipathat the end of the name.
The table names for the Omnipath database will be:
interactions_omnipathenzsub_omnipathcomplexes_omnipathintercell_omnipathannotations_omnipath
For our MVP we will be working on the interactions_omnipath table. This table consist of the following schema:
| Column Name | Data Type (SQL alchemy) | Data Type (Django ORM) | Nullable | Auto Increment | Default |
|---|---|---|---|---|---|
| id | Integer | models.IntegerField(primary_key=True) | ✓ | ||
| source | String | models.CharField(null=True, blank=True) | ✓ | ||
| target | String | models.CharField(null=True, blank=True) | ✓ | ||
| source_genesymbol | String | models.CharField(null=False, blank=True) | |||
| target_genesymbol | String | models.CharField(null=False, blank=True) | |||
| is_directed | Boolean | models.BooleanField() | |||
| is_stimulation | Boolean | models.BooleanField() | |||
| is_inhibition | Boolean | models.BooleanField() | |||
| consensus_direction | Boolean | models.BooleanField() | |||
| consensus_stimulation | Boolean | models.BooleanField() | |||
| consensus_inhibition | Boolean | models.BooleanField() | |||
| sources | ARRAY(String) | models.ArrayField(models.CharField(max_length=255)) | |||
| references | String | models.CharField(null=False, blank=True) | |||
| omnipath | Boolean | models.BooleanField() | |||
| kinaseextra | Boolean | models.BooleanField() | |||
| ligrecextra | Boolean | models.BooleanField() | |||
| pathwayextra | Boolean | models.BooleanField() | |||
| mirnatarget | Boolean | models.BooleanField() | |||
| dorothea | Boolean | models.BooleanField() | |||
| collectri | Boolean | models.BooleanField() | |||
| tf_target | Boolean | models.BooleanField() | |||
| lncrna_mrna | Boolean | models.BooleanField() | |||
| tf_mirna | Boolean | models.BooleanField() | |||
| small_molecule | Boolean | models.BooleanField() | |||
| dorothea_curated | Boolean | models.BooleanField() | |||
| dorothea_chipseq | Boolean | models.BooleanField() | |||
| dorothea_tfbs | Boolean | models.BooleanField() | |||
| dorothea_coexp | Boolean | models.BooleanField() | |||
| dorothea_level | ARRAY(String) | models.ArrayField(models.CharField(max_length=255)) | |||
| type | String | models.CharField(null=False, blank=True) | |||
| curation_effort | Integer | models.IntegerField() | |||
| extra_attrs | JSONB | models.JSONField(null=True, blank=True) | ✓ | ||
| evidences | JSONB | models.JSONField(null=True, blank=True) | ✓ | ||
| ncbi_tax_id_source | Integer | models.IntegerField() | |||
| entity_type_source | String | models.CharField(null=False, blank=True) | |||
| ncbi_tax_id_target | Integer | models.IntegerField() | |||
| entity_type_target | String | models.CharField(null=False, blank=True) |
- Create a model or blueprint for each table. Open the file
omnipath_server_django/api/models.pyfile. This file will contains all the classes that represent the tables. In our case we are going to create just one class for the tableinteractions_omnipath
from django.db import models
# Model for the table `interactions_omnipath`.
class InteractionsOmnipath(models.Model):
source = models.CharField(null=True, blank=True)
target = models.CharField(null=True, blank=True)
source_genesymbol = models.CharField(null=False, blank=True)
target_genesymbol = models.CharField(null=False, blank=True)
is_directed = models.BooleanField()
is_stimulation = models.BooleanField()
is_inhibition = models.BooleanField()
consensus_direction = models.BooleanField()
consensus_stimulation = models.BooleanField()
consensus_inhibition = models.BooleanField()
sources = models.ArrayField(models.CharField(max_length=255))
references = models.CharField(null=False, blank=True)
omnipath = models.BooleanField()
kinaseextra = models.BooleanField()
ligrecextra = models.BooleanField()
pathwayextra = models.BooleanField()
mirnatarget = models.BooleanField()
dorothea = models.BooleanField()
collectri = models.BooleanField()
tf_target = models.BooleanField()
lncrna_mrna = models.BooleanField()
tf_mirna = models.BooleanField()
small_molecule = models.BooleanField()
dorothea_curated = models.BooleanField()
dorothea_chipseq = models.BooleanField()
dorothea_tfbs = models.BooleanField()
dorothea_coexp = models.BooleanField()
dorothea_level = models.ArrayField(models.CharField(max_length=255))
type = models.CharField(null=False, blank=True)
curation_effort = models.IntegerField()
extra_attrs = models.JSONField(null=True, blank=True)
evidences = models.JSONField(null=True, blank=True)
ncbi_tax_id_source = models.IntegerField()
entity_type_source = models.CharField(null=False, blank=True)
ncbi_tax_id_target = models.IntegerField()
entity_type_target = models.CharField(null=False, blank=True)
class Meta:
db_table = "interactions_omnipath" # Name of the table in the database
verbose_name = (
"Interactions Omnipath" # Optional, for human-readable name in Django admin
)
ordering = ("id",)- Create a file in
/api/serializers.py. This file will serve to create encoding and decoding classes.
from rest_framework import serializers
from api.models import InteractionsOmnipath
class InteractionsOmnipathSerializer(serializers.ModelSerializer):
class Meta:
model = InteractionsOmnipath
fields = ("id", "source", "target") # Just two fields for this example- Run the following command
poetry run python manage.py createsuperuserFields
- Username: django_admin
- Password: omnipath_admin_123
- Email address: edwin1892@gmail.com
- in
omnipath_server_django/urls.py
from django.urls import re_path
from . import views
urlpatterns = [
re_path(r"^api/interactions$", views.interactions_list),
re_path(r"^api/interactions/(?P<pk>[0-9]+)$", views.interaction_detail),
]- In
api/urls.py
from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("api.urls")),
]- In
api/admin.pyinser the following
from django.contrib import admin
from .models import In