# Observation Portal
![Build](https://github.com/observatorycontrolsystem/observation-portal/workflows/Build/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/observatorycontrolsystem/observation-portal/badge.svg?branch=master)](https://coveralls.io/github/observatorycontrolsystem/observation-portal?branch=master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9846cee7c4904cae8864525101030169)](https://www.codacy.com/gh/observatorycontrolsystem/observation-portal?utm_source=github.com&utm_medium=referral&utm_content=observatorycontrolsystem/observation-portal&utm_campaign=Badge_Grade)
## An API for Astronomical Observation Management
Within an observatory control system, the observation portal provides modules for:
- **Proposal management**: Calls for proposals, proposal creation, and time allocation
- **Request management**: Observation request validation, submission, and cancellation, as well as views providing ancillary information about them
- **Observation management**: Store and provide the telescope schedule, update observations, and update observation requests on observation update
- **User identity management**: Oauth2 authenticated user management that can be used in other applications
## Prerequisites
Optional prerequisites can be skipped for reduced functionality.
- Python >= 3.8
- PostgreSQL >= 14
- A running [Configuration Database](https://github.com/observatorycontrolsystem/configdb)
- (Optional) A running [Downtime Database](https://github.com/observatorycontrolsystem/downtime)
- (Optional) A running Elasticsearch
## Environment Variables
| | Variable | Description | Default |
| ---------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| General | `DEBUG` | Whether the application should run using Django's debug mode | `False` |
| | `SECRET_KEY` | The secret key used for sessions | _`random characters`_ |
| | `ALLOWED_HOSTS` | Override for Django's ALLOWED_HOSTS setting | `*` |
| | `CSRF_TRUSTED_ORIGINS` | Comma separated list of trusted origins allowed for CSRF | `None`
| | `MAX_FAILURES_PER_REQUEST` | Maximum number of times an Observation can fail per Request before the Request is marked as FAILURE_LIMIT_REACHED. 0 means there is no max. | `0` |
| | `MAX_IPP_VALUE` | The maximum value to be used for ipp scaling. Should be greater than 1 (1 would be no scaling) | `2.0` |
| | `MIN_IPP_VALUE` | The minimum value to be used for ipp scaling. Should be less than 1 but greater than 0 | `0.5` |
| | `PROPOSAL_TIME_OVERUSE_ALLOWANCE` | The amount of leeway in a proposals timeallocation before rejecting that request for scheduling. For example, a value of 1.1 results in allows over-scheduling by up to 10% of the total time_allocation. It is useful to allow some over-scheduling since it is likely some in progress observations will use less time then allocated, due to conservative overheads, failing, or cancelling. | `1.1` |
| Database | `DB_NAME` | The name of the database | `observation_portal` |
| | `DB_USER` | The database user | `postgres` |
| | `DB_PASSWORD` | The database password | _`Empty string`_ |
| | `DB_HOST` | The database host | `127.0.0.1` |
| | `DB_PORT` | The database port | `5432` |
| Cache | `CACHE_BACKEND` | The remote Django cache backend | `django.core.cache.backends.locmem.LocMemCache` |
| | `CACHE_LOCATION` | The cache location or connection string | `unique-snowflake` |
| | `LOCAL_CACHE_BACKEND` | The local Django cache backend to use | `django.core.cache.backends.locmem.LocMemCache` |
| Static and Media Files | `AWS_BUCKET_NAME` | The name of the AWS bucket in which to store static and media files | `observation-portal-test-bucket` |
| | `AWS_REGION` | The AWS region | `us-west-2` |
| | `AWS_ACCESS_KEY_ID` | The AWS user access key with read/write priveleges on the s3 bucket | `None` |
| | `AWS_SECRET_ACCESS_KEY` | The AWS user secret key to use with the access key | `None` |
| | `MEDIA_STORAGE` | The Django media files storage backend | `django.core.files.storage.FileSystemStorage` |
| | `MEDIAFILES_DIR` | The directory in which to store media files | `media` |
| | `STATIC_STORAGE` | The Django static files storage backend | `django.contrib.staticfiles.storage.StaticFilesStorage` |
| Email | `EMAIL_BACKEND` | The Django SMTP backend to use | `django.core.mail.backends.console.EmailBackend` |
| | `EMAIL_HOST` | The SMTP host | `localhost` |
| | `EMAIL_HOST_USER` | The SMTP user | _`Empty string`_ |
| | `EMAIL_HOST_PASSWORD` | The SMTP password | _`Empty string`_ |
| | `EMAIL_PORT` | The SMTP port | `587` |
| | `ORGANIZATION_EMAIL` | The reply-to email for outgoing messages | _`Empty string`_ |
| | `ORGANIZATION_DDT_EMAIL` | Email to receive ddt science application submission messages | _`Empty string`_ |
| | `ORGANIZATION_ADMIN_EMAIL` | The Django Admin email to receive http 500 reports. | _`Empty string`_ |
| | `ORGANIZATION_SUPPORT_EMAIL` | Email to receive account removal requests | _`Empty string`_ |
| | `ORGANIZATION_NAME` | The name of your organization, used within email templates | _`Empty string`_ |
| | `OBSERVATORY_DIRECTOR_NAME` | Full name of the observatory director, used within email templates | _`Foo Bar`_ |
| | `OBSERVATION_PORTAL_BASE_URL` | The base url of your deployed Observation Portal code, used within email templates to provide links to pages | `http://localhost` |
| | `REQUESTGROUP_DATA_DOWNLOAD_URL` | The url where a user can download requestgroup data. Optionally include `{requestgroup_id}` in the string which will be filled in with the ID of the specific requestgroup. | _`Empty string`_ |
| | `REQUEST_DETAIL_URL` | The url to frontend detail page for a Request. Optionally include `{request_id}` in the string which will be filled in with the ID of the specific request. | _`Empty string`_ |
| | `SCIENCE_APPLICATION_DETAIL_URL` | The url to frontend science application detail page. Optionally include `{sciapp_id}` in the string which will be filled in with the ID of the specific science application. | _`Empty string`_ |
| External Services | `CONFIGDB_URL` | The url to the configuration database | `http://localhost` |
| | `DOWNTIMEDB_URL` | The url to the downtime database | `http://localhost` |
| | `OPENSEARCH_URL` | The url to the OpenSearch cluster | `http://localhost` |
| Authentication | `OAUTH_SERVER_KEY` | The secret key for client applications to verify against for authentication calls | _`Empty string`_ |
| | `OAUTH_CLIENT_APPS_BASE_URLS` | Comma delimited set of base urls for client applications. This server will update those clients on any change in user accounts or api tokens. | _`Empty string`_ |
| Task Scheduling | `DRAMATIQ_BROKER_URL` | The url to the dramatiq broker (if set takes precedence over `DRAMATIQ_BROKER_HOST` & `DRAMATIQ_BROKER_PORT` | `redis://redis:6379/0` |
| | `DRAMATIQ_BROKER_HOST` | The broker host for dramatiq (deprecated) | `redis` |
| | `DRAMATIQ_BROKER_PORT` | The broker port for dramatiq (deprecated) | `6379` |
| Throttle Overrides | `REQUESTGROUPS_CANCEL_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups cancel endpoint | `2000/day` |
| | `REQUESTGROUPS_CREATE_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups create endpoint | `5000/day` |
| | `REQUESTGROUPS_VALIDATE_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups validate endpoint | `20000/day` |
| Realtime Overrides | `REAL_TIME_AVAILABILITY_DAYS_OUT` | For the /api/realtime/availability/ endpoint - controls how many minutes after the current time a realtime session should be available as a lower bound | `60` |
| | `REAL_TIME_AVAILABILITY_MINUTES_IN` | For the /api/realtime/availability/ endpoint - controls how many days after the current time a realtime session should be available as an upper bound | `7` |
| Serializer Overrides | `OBSERVATIONS_SUMMARY_SERIALIZER` | Class dotpath for Observation's Summary serializer override | `observation_portal.observations.serializers.SummarySerializer` |
| | `OBSERVATIONS_CONFIGURATIONSTATUS_SERIALIZER` | Class dotpath for Observation's ConfigurationStatus serializer override | `observation_portal.observations.serializers.ConfigurationStatusSerializer` |
| | `OBSERVATIONS_TARGET_SERIALIZER` | Class dotpath for Observation's Target serializer override | `observation_portal.observations.serializers.ObservationTargetSerializer` |
| | `OBSERVATIONS_CONFIGURATION_SERIALIZER` | Class dotpath for Observation's Configuration serializer override | `observation_portal.observations.serializers.ObservationConfigurationSerializer` |
| | `OBSERVATIONS_REQUEST_SERIALIZER` | Class dotpath for Observation's Request serializer override | `observation_portal.observations.serializers.ObserveRequestSerializer` |
| | `OBSERVATIONS_REQUESTGROUP_SERIALIZER` | Class dotpath for Observation's RequestGroup serializer override | `observation_portal.observations.serializers.ObserveRequestGroupSerializer` |
| | `OBSERVATIONS_SCHEDULE_SERIALIZER` | Class dotpath for Observation's Schedule serializer override | `observation_portal.observations.serializers.ScheduleSerializer` |
| | `OBSERVATIONS_OBSERVATION_SERIALIZER` | Class dotpath for Observation's Observation serializer override | `observation_portal.observations.serializers.ObservationSerializer` |
| | `OBSERVATIONS_CANCEL_SERIALIZER` | Class dotpath for Observation's Cancel Observation serializer override | `observation_portal.observations.serializers.CancelObservationsSerializer` |
| | `REQUESTGROUPS_CADENCE_SERIALIZER` | Class dotpath for RequestGroups's Cadence serializer override | `observation_portal.requestgroups.serializers.CadenceSerializer` |
| | `REQUESTGROUPS_CADENCEREQUEST_SERIALIZER` | Class dotpath for RequestGroups's Cadence Request serializer override | `observation_portal.requestgroups.serializers.CadenceRequestSerializer` |
| | `REQUESTGROUPS_CONSTRAINTS_SERIALIZER` | Class dotpath for RequestGroups's Constraints serializer override | `observation_portal.requestgroups.serializers.ConstraintsSerializer` |
| | `REQUESTGROUPS_REGIONOFINTEREST_SERIALIZER` | Class dotpath for RequestGroups's Instrument Config ROI serializer override | `observation_portal.requestgroups.serializers.RegionOfInterestSerializer` |
| | `REQUESTGROUPS_INSTRUMENTCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Instrument Config serializer override | `observation_portal.requestgroups.serializers.InstrumentConfigSerializer` |
| | `REQUESTGROUPS_ACQUISITIONCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Acquisition Config serializer override | `observation_portal.requestgroups.serializers.AcquisitionConfigSerializer` |
| | `REQUESTGROUPS_GUIDINGCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Guiding Config serializer override | `observation_portal.requestgroups.serializers.GuidingConfigSerializer` |
| | `REQUESTGROUPS_TARGET_SERIALIZER` | Class dotpath for RequestGroups's Target serializer override | `observation_portal.requestgroups.serializers.TargetSerializer` |
| | `REQUESTGROUPS_CONFIGURATION_SERIALIZER` | Class dotpath for RequestGroups's Configuration serializer override | `observation_portal.requestgroups.serializers.ConfigurationSerializer` |
| | `REQUESTGROUPS_LOCATION_SERIALIZER` | Class dotpath for RequestGroups's Location serializer override | `observation_portal.requestgroups.serializers.LocationSerializer` |
| | `REQUESTGROUPS_WINDOW_SERIALIZER` | Class dotpath for RequestGroups's Window serializer override | `observation_portal.requestgroups.serializers.WindowSerializer` |
| | `REQUESTGROUPS_REQUEST_SERIALIZER` | Class dotpath for RequestGroups's Request serializer override | `observation_portal.requestgroups.serializers.RequestSerializer` |
| | `REQUESTGROUPS_REQUESTGROUP_SERIALIZER` | Class dotpath for RequestGroups's RequestGroup serializer override | `observation_portal.requestgroups.serializers.RequestGroupSerializer` |
| | `REQUESTGROUPS_DRAFTREQUESTGROUP_SERIALIZER` | Class dotpath for RequestGroups's Draft RequestGroup serializer override | `observation_portal.requestgroups.serializers.DraftRequestGroupSerializer` |
| | `PROPOSALS_PROPOSAL_SERIALIZER` | Class dotpath for Proposal's Proposal serializer override | `observation_portal.proposals.serializers.ProposalSerializer` |
| | `PROPOSALS_PROPOSALINVITE_SERIALIZER` | Class dotpath for Proposal's ProposalInvite serializer override | `observation_portal.proposals.serializers.ProposalInviteSerializer` |
| | `PROPOSALS_SEMESTER_SERIALIZER` | Class dotpath for Proposal's Semester serializer override | `observation_portal.proposals.serializers.SemesterSerialzer` |
| | `PROPOSALS_MEMBERSHIP_SERIALIZER` | Class dotpath for Proposal's Membership serializer override | `observation_portal.proposals.serializers.MembershipSerializer` |
| | `PROPOSALS_PROPOSALNOTIFICATION_SERIALIZER` | Class dotpath for Proposal's ProposalNotification serializer override | `observation_portal.proposals.serializers.ProposalNotificationSerializer` |
| | `PROPOSALS_TIMELIMIT_SERIALIZER` | Class dotpath for Proposal's Proposal serializer override | `observation_portal.proposals.serializers.TimeLimitSerializer` |
| | `ACCOUNTS_PROFILE_SERIALIZER` | Class dotpath for Accounts's Profile serializer override | `observation_portal.accounts.serializers.ProfileSerializer` |
| | `ACCOUNTS_USER_SERIALIZER` | Class dotpath for Accounts's User serializer override | `observation_portal.accounts.serializers.UserSerializer` |
| | `ACCOUNTS_ACCOUNTREMOVAL_SERIALIZER` | Class dotpath for Accounts's Account Removal serializer override | `observation_portal.accounts.serializers.AccountRemovalSerializer` |
| | `SCIAPPLICATIONS_CALL_SERIALIZER` | Class dotpath for SciApplications's Call serializer override | `observation_portal.sciapplications.serializers.CallSerializer` |
| | `SCIAPPLICATIONS_SCIENCEAPPLICATION_SERIALIZER` | Class dotpath for SciApplications's Science Application serializer override | `observation_portal.sciapplications.serializers.ScienceApplicationSerializer` |
| as_dict Overrides | `OBSERVATIONS_SUMMARY_AS_DICT` | Class dotpath for Observation's Summary as_dict override | `observation_portal.observations.models.summary_as_dict` |
| | `OBSERVATIONS_CONFIGURATIONSTATUS_AS_DICT` | Class dotpath for Observation's ConfigurationStatus as_dict override | `observation_portal.observations.models.configurationstatus_as_dict` |
| | `OBSERVATIONS_OBSERVATION_AS_DICT` | Class dotpath for Observation's Observation as_dict override | `observation_portal.observations.models.observation_as_dict` |
| | `REQUESTGROUPS_CONSTRAINTS_AS_DICT` | Class dotpath for RequestGroups's Constraints as_dict override | `observation_portal.requestgroups.models.constraints_as_dict` |
| | `REQUESTGROUPS_REGIONOFINTEREST_AS_DICT` | Class dotpath for RequestGroups's Instrument Config ROI as_dict override | `observation_portal.requestgroups.models.regionofinterest_as_dict` |
| | `REQUESTGROUPS_INSTRUMENTCONFIG_AS_DICT` | Class dotpath for RequestGroups's Instrument Config as_dict override | `observation_portal.requestgroups.models.instrumentconfig_as_dict` |
| | `REQUESTGROUPS_ACQUISITIONCONFIG_AS_DICT` | Class dotpath for RequestGroups's Acquisition Config as_dict override | `observation_portal.requestgroups.models.acquisitionconfig_as_dict` |
| | `REQUESTGROUPS_GUIDINGCONFIG_AS_DICT` | Class dotpath for RequestGroups's Guiding Config as_dict override | `observation_portal.requestgroups.models.guidingconfig_as_dict` |
| | `REQUESTGROUPS_TARGET_AS_DICT` | Class dotpath for RequestGroups's Target as_dict override | `observation_portal.requestgroups.models.target_as_dict` |
| | `REQUESTGROUPS_CONFIGURATION_AS_DICT` | Class dotpath for RequestGroups's Configuration as_dict override | `observation_portal.requestgroups.models.configuration_as_dict` |
| | `REQUESTGROUPS_LOCATION_AS_DICT` | Class dotpath for RequestGroups's Location as_dict override | `observation_portal.requestgroups.models.location_as_dict` |
| | `REQUESTGROUPS_WINDOW_AS_DICT` | Class dotpath for RequestGroups's Window as_dict override | `observation_portal.requestgroups.models.window_as_dict` |
| | `REQUESTGROUPS_REQUEST_AS_DICT` | Class dotpath for RequestGroups's Request as_dict override | `observation_portal.requestgroups.models.request_as_dict` |
| | `REQUESTGROUPS_REQUESTGROUP_AS_DICT` | Class dotpath for RequestGroups's RequestGroup as_dict override | `observation_portal.requestgroups.models.requestgroup_as_dict` |
| | `PROPOSALS_PROPOSAL_AS_DICT` | Class dotpath for Proposal's Proposal as_dict override | `observation_portal.proposals.models.proposal_as_dict` |
| | `PROPOSALS_TIMEALLOCATION_AS_DICT` | Class dotpath for Proposal's TimeAllocation as_dict override | `observation_portal.proposals.models.timeallocation_as_dict` |
| | `PROPOSALS_MEMBERSHIP_AS_DICT` | Class dotpath for Proposal's Membership as_dict override | `observation_portal.proposals.models.membership_as_dict` |
| duration Overrides | `INSTRUMENT_CONFIGURATION_PER_EXPOSURE_DURATION` | Class dotpath for duration_per_exposure method override | `observation_portal.requestgroups.duration_utils.get_instrument_configuration_duration_per_exposure` |
## Local Development
### **Set up external services**
Please refer to the [Configuration Database](https://github.com/observatorycontrolsystem/configdb) and [Downtime Database](https://github.com/observatorycontrolsystem/downtime) projects for instructions on how to get those running, as well as the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/install-elasticsearch.html) for options on how to run Elasticsearch.
### **Poetry**
We use Poetry for package management. If you already have Poetry installed, you
can skip this section.
You can install Poetry using one of the many options listed at https://python-poetry.org/docs/#installation.
One simple option is using Pipx:
python3 -m pip install --user pipx
python3 -m pipx ensurepath
pipx install poetry
### **Install**
Install the project and its Python dependencies:
poetry install
This will install the project in a Poetry managed virtual environment. To run
commands in that environment either use `poetry run ...` or start a shell in
that environment with `poetry shell`
### **Set up the database**
This example uses the [PostgreSQL Docker image](https://hub.docker.com/_/postgres) to create a database. Make sure that the options that you use to set up your database correspond with your configured database settings.
docker run --name observation-portal-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=observation_portal -v/var/lib/postgresql/data -p5432:5432 -d postgres:11.1
After creating the database, migrations must be applied to set up the tables in the database.
poetry run python manage.py migrate
### **Run the tests**
poetry run python manage.py test --settings=observation_portal.test_settings
### **Run the portal**
poetry run python manage.py runserver
The observation portal should now be accessible from <http://127.0.0.1:8000>!
Raw data
{
"_id": null,
"home_page": "https://observatorycontrolsystem.github.io",
"name": "django-ocs-observation-portal",
"maintainer": null,
"docs_url": null,
"requires_python": "<3.11,>=3.8",
"maintainer_email": null,
"keywords": "observations, astronomy, astrophysics, cosmology, science",
"author": "Observatory Control System Project",
"author_email": "ocs@lco.global",
"download_url": "https://files.pythonhosted.org/packages/aa/05/c4e3c2ab851bcf0a84a5b6ce12fd4148603d1b6a43094966faf3039cd5e0/django_ocs_observation_portal-4.13.3.tar.gz",
"platform": null,
"description": "# Observation Portal\n\n![Build](https://github.com/observatorycontrolsystem/observation-portal/workflows/Build/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/observatorycontrolsystem/observation-portal/badge.svg?branch=master)](https://coveralls.io/github/observatorycontrolsystem/observation-portal?branch=master)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9846cee7c4904cae8864525101030169)](https://www.codacy.com/gh/observatorycontrolsystem/observation-portal?utm_source=github.com&utm_medium=referral&utm_content=observatorycontrolsystem/observation-portal&utm_campaign=Badge_Grade)\n\n## An API for Astronomical Observation Management\n\nWithin an observatory control system, the observation portal provides modules for:\n\n- **Proposal management**: Calls for proposals, proposal creation, and time allocation\n- **Request management**: Observation request validation, submission, and cancellation, as well as views providing ancillary information about them\n- **Observation management**: Store and provide the telescope schedule, update observations, and update observation requests on observation update\n- **User identity management**: Oauth2 authenticated user management that can be used in other applications\n\n## Prerequisites\n\nOptional prerequisites can be skipped for reduced functionality.\n\n- Python >= 3.8\n- PostgreSQL >= 14\n- A running [Configuration Database](https://github.com/observatorycontrolsystem/configdb) \n- (Optional) A running [Downtime Database](https://github.com/observatorycontrolsystem/downtime)\n- (Optional) A running Elasticsearch\n\n\n\n## Environment Variables\n\n| | Variable | Description | Default |\n| ---------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| General | `DEBUG` | Whether the application should run using Django's debug mode | `False` |\n| | `SECRET_KEY` | The secret key used for sessions | _`random characters`_ |\n| | `ALLOWED_HOSTS` | Override for Django's ALLOWED_HOSTS setting | `*` |\n| | `CSRF_TRUSTED_ORIGINS` | Comma separated list of trusted origins allowed for CSRF | `None`\n| | `MAX_FAILURES_PER_REQUEST` | Maximum number of times an Observation can fail per Request before the Request is marked as FAILURE_LIMIT_REACHED. 0 means there is no max. | `0` |\n| | `MAX_IPP_VALUE` | The maximum value to be used for ipp scaling. Should be greater than 1 (1 would be no scaling) | `2.0` |\n| | `MIN_IPP_VALUE` | The minimum value to be used for ipp scaling. Should be less than 1 but greater than 0 | `0.5` |\n| | `PROPOSAL_TIME_OVERUSE_ALLOWANCE` | The amount of leeway in a proposals timeallocation before rejecting that request for scheduling. For example, a value of 1.1 results in allows over-scheduling by up to 10% of the total time_allocation. It is useful to allow some over-scheduling since it is likely some in progress observations will use less time then allocated, due to conservative overheads, failing, or cancelling. | `1.1` |\n| Database | `DB_NAME` | The name of the database | `observation_portal` |\n| | `DB_USER` | The database user | `postgres` |\n| | `DB_PASSWORD` | The database password | _`Empty string`_ |\n| | `DB_HOST` | The database host | `127.0.0.1` |\n| | `DB_PORT` | The database port | `5432` |\n| Cache | `CACHE_BACKEND` | The remote Django cache backend | `django.core.cache.backends.locmem.LocMemCache` |\n| | `CACHE_LOCATION` | The cache location or connection string | `unique-snowflake` |\n| | `LOCAL_CACHE_BACKEND` | The local Django cache backend to use | `django.core.cache.backends.locmem.LocMemCache` |\n| Static and Media Files | `AWS_BUCKET_NAME` | The name of the AWS bucket in which to store static and media files | `observation-portal-test-bucket` |\n| | `AWS_REGION` | The AWS region | `us-west-2` |\n| | `AWS_ACCESS_KEY_ID` | The AWS user access key with read/write priveleges on the s3 bucket | `None` |\n| | `AWS_SECRET_ACCESS_KEY` | The AWS user secret key to use with the access key | `None` |\n| | `MEDIA_STORAGE` | The Django media files storage backend | `django.core.files.storage.FileSystemStorage` |\n| | `MEDIAFILES_DIR` | The directory in which to store media files | `media` |\n| | `STATIC_STORAGE` | The Django static files storage backend | `django.contrib.staticfiles.storage.StaticFilesStorage` |\n| Email | `EMAIL_BACKEND` | The Django SMTP backend to use | `django.core.mail.backends.console.EmailBackend` |\n| | `EMAIL_HOST` | The SMTP host | `localhost` |\n| | `EMAIL_HOST_USER` | The SMTP user | _`Empty string`_ |\n| | `EMAIL_HOST_PASSWORD` | The SMTP password | _`Empty string`_ |\n| | `EMAIL_PORT` | The SMTP port | `587` |\n| | `ORGANIZATION_EMAIL` | The reply-to email for outgoing messages | _`Empty string`_ |\n| | `ORGANIZATION_DDT_EMAIL` | Email to receive ddt science application submission messages | _`Empty string`_ |\n| | `ORGANIZATION_ADMIN_EMAIL` | The Django Admin email to receive http 500 reports. | _`Empty string`_ |\n| | `ORGANIZATION_SUPPORT_EMAIL` | Email to receive account removal requests | _`Empty string`_ |\n| | `ORGANIZATION_NAME` | The name of your organization, used within email templates | _`Empty string`_ |\n| | `OBSERVATORY_DIRECTOR_NAME` | Full name of the observatory director, used within email templates | _`Foo Bar`_ |\n| | `OBSERVATION_PORTAL_BASE_URL` | The base url of your deployed Observation Portal code, used within email templates to provide links to pages | `http://localhost` |\n| | `REQUESTGROUP_DATA_DOWNLOAD_URL` | The url where a user can download requestgroup data. Optionally include `{requestgroup_id}` in the string which will be filled in with the ID of the specific requestgroup. | _`Empty string`_ |\n| | `REQUEST_DETAIL_URL` | The url to frontend detail page for a Request. Optionally include `{request_id}` in the string which will be filled in with the ID of the specific request. | _`Empty string`_ |\n| | `SCIENCE_APPLICATION_DETAIL_URL` | The url to frontend science application detail page. Optionally include `{sciapp_id}` in the string which will be filled in with the ID of the specific science application. | _`Empty string`_ |\n| External Services | `CONFIGDB_URL` | The url to the configuration database | `http://localhost` |\n| | `DOWNTIMEDB_URL` | The url to the downtime database | `http://localhost` |\n| | `OPENSEARCH_URL` | The url to the OpenSearch cluster | `http://localhost` |\n| Authentication | `OAUTH_SERVER_KEY` | The secret key for client applications to verify against for authentication calls | _`Empty string`_ |\n| | `OAUTH_CLIENT_APPS_BASE_URLS` | Comma delimited set of base urls for client applications. This server will update those clients on any change in user accounts or api tokens. | _`Empty string`_ |\n| Task Scheduling | `DRAMATIQ_BROKER_URL` | The url to the dramatiq broker (if set takes precedence over `DRAMATIQ_BROKER_HOST` & `DRAMATIQ_BROKER_PORT` | `redis://redis:6379/0` |\n| | `DRAMATIQ_BROKER_HOST` | The broker host for dramatiq (deprecated) | `redis` |\n| | `DRAMATIQ_BROKER_PORT` | The broker port for dramatiq (deprecated) | `6379` |\n| Throttle Overrides | `REQUESTGROUPS_CANCEL_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups cancel endpoint | `2000/day` |\n| | `REQUESTGROUPS_CREATE_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups create endpoint | `5000/day` |\n| | `REQUESTGROUPS_VALIDATE_DEFAULT_THROTTLE` | Default django rest framework throttle rate string for the RequestGroups validate endpoint | `20000/day` |\n| Realtime Overrides | `REAL_TIME_AVAILABILITY_DAYS_OUT` | For the /api/realtime/availability/ endpoint - controls how many minutes after the current time a realtime session should be available as a lower bound | `60` |\n| | `REAL_TIME_AVAILABILITY_MINUTES_IN` | For the /api/realtime/availability/ endpoint - controls how many days after the current time a realtime session should be available as an upper bound | `7` |\n| Serializer Overrides | `OBSERVATIONS_SUMMARY_SERIALIZER` | Class dotpath for Observation's Summary serializer override | `observation_portal.observations.serializers.SummarySerializer` |\n| | `OBSERVATIONS_CONFIGURATIONSTATUS_SERIALIZER` | Class dotpath for Observation's ConfigurationStatus serializer override | `observation_portal.observations.serializers.ConfigurationStatusSerializer` |\n| | `OBSERVATIONS_TARGET_SERIALIZER` | Class dotpath for Observation's Target serializer override | `observation_portal.observations.serializers.ObservationTargetSerializer` |\n| | `OBSERVATIONS_CONFIGURATION_SERIALIZER` | Class dotpath for Observation's Configuration serializer override | `observation_portal.observations.serializers.ObservationConfigurationSerializer` |\n| | `OBSERVATIONS_REQUEST_SERIALIZER` | Class dotpath for Observation's Request serializer override | `observation_portal.observations.serializers.ObserveRequestSerializer` |\n| | `OBSERVATIONS_REQUESTGROUP_SERIALIZER` | Class dotpath for Observation's RequestGroup serializer override | `observation_portal.observations.serializers.ObserveRequestGroupSerializer` |\n| | `OBSERVATIONS_SCHEDULE_SERIALIZER` | Class dotpath for Observation's Schedule serializer override | `observation_portal.observations.serializers.ScheduleSerializer` |\n| | `OBSERVATIONS_OBSERVATION_SERIALIZER` | Class dotpath for Observation's Observation serializer override | `observation_portal.observations.serializers.ObservationSerializer` |\n| | `OBSERVATIONS_CANCEL_SERIALIZER` | Class dotpath for Observation's Cancel Observation serializer override | `observation_portal.observations.serializers.CancelObservationsSerializer` |\n| | `REQUESTGROUPS_CADENCE_SERIALIZER` | Class dotpath for RequestGroups's Cadence serializer override | `observation_portal.requestgroups.serializers.CadenceSerializer` |\n| | `REQUESTGROUPS_CADENCEREQUEST_SERIALIZER` | Class dotpath for RequestGroups's Cadence Request serializer override | `observation_portal.requestgroups.serializers.CadenceRequestSerializer` |\n| | `REQUESTGROUPS_CONSTRAINTS_SERIALIZER` | Class dotpath for RequestGroups's Constraints serializer override | `observation_portal.requestgroups.serializers.ConstraintsSerializer` |\n| | `REQUESTGROUPS_REGIONOFINTEREST_SERIALIZER` | Class dotpath for RequestGroups's Instrument Config ROI serializer override | `observation_portal.requestgroups.serializers.RegionOfInterestSerializer` |\n| | `REQUESTGROUPS_INSTRUMENTCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Instrument Config serializer override | `observation_portal.requestgroups.serializers.InstrumentConfigSerializer` |\n| | `REQUESTGROUPS_ACQUISITIONCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Acquisition Config serializer override | `observation_portal.requestgroups.serializers.AcquisitionConfigSerializer` |\n| | `REQUESTGROUPS_GUIDINGCONFIG_SERIALIZER` | Class dotpath for RequestGroups's Guiding Config serializer override | `observation_portal.requestgroups.serializers.GuidingConfigSerializer` |\n| | `REQUESTGROUPS_TARGET_SERIALIZER` | Class dotpath for RequestGroups's Target serializer override | `observation_portal.requestgroups.serializers.TargetSerializer` |\n| | `REQUESTGROUPS_CONFIGURATION_SERIALIZER` | Class dotpath for RequestGroups's Configuration serializer override | `observation_portal.requestgroups.serializers.ConfigurationSerializer` |\n| | `REQUESTGROUPS_LOCATION_SERIALIZER` | Class dotpath for RequestGroups's Location serializer override | `observation_portal.requestgroups.serializers.LocationSerializer` |\n| | `REQUESTGROUPS_WINDOW_SERIALIZER` | Class dotpath for RequestGroups's Window serializer override | `observation_portal.requestgroups.serializers.WindowSerializer` |\n| | `REQUESTGROUPS_REQUEST_SERIALIZER` | Class dotpath for RequestGroups's Request serializer override | `observation_portal.requestgroups.serializers.RequestSerializer` |\n| | `REQUESTGROUPS_REQUESTGROUP_SERIALIZER` | Class dotpath for RequestGroups's RequestGroup serializer override | `observation_portal.requestgroups.serializers.RequestGroupSerializer` |\n| | `REQUESTGROUPS_DRAFTREQUESTGROUP_SERIALIZER` | Class dotpath for RequestGroups's Draft RequestGroup serializer override | `observation_portal.requestgroups.serializers.DraftRequestGroupSerializer` |\n| | `PROPOSALS_PROPOSAL_SERIALIZER` | Class dotpath for Proposal's Proposal serializer override | `observation_portal.proposals.serializers.ProposalSerializer` |\n| | `PROPOSALS_PROPOSALINVITE_SERIALIZER` | Class dotpath for Proposal's ProposalInvite serializer override | `observation_portal.proposals.serializers.ProposalInviteSerializer` |\n| | `PROPOSALS_SEMESTER_SERIALIZER` | Class dotpath for Proposal's Semester serializer override | `observation_portal.proposals.serializers.SemesterSerialzer` |\n| | `PROPOSALS_MEMBERSHIP_SERIALIZER` | Class dotpath for Proposal's Membership serializer override | `observation_portal.proposals.serializers.MembershipSerializer` |\n| | `PROPOSALS_PROPOSALNOTIFICATION_SERIALIZER` | Class dotpath for Proposal's ProposalNotification serializer override | `observation_portal.proposals.serializers.ProposalNotificationSerializer` |\n| | `PROPOSALS_TIMELIMIT_SERIALIZER` | Class dotpath for Proposal's Proposal serializer override | `observation_portal.proposals.serializers.TimeLimitSerializer` |\n| | `ACCOUNTS_PROFILE_SERIALIZER` | Class dotpath for Accounts's Profile serializer override | `observation_portal.accounts.serializers.ProfileSerializer` |\n| | `ACCOUNTS_USER_SERIALIZER` | Class dotpath for Accounts's User serializer override | `observation_portal.accounts.serializers.UserSerializer` |\n| | `ACCOUNTS_ACCOUNTREMOVAL_SERIALIZER` | Class dotpath for Accounts's Account Removal serializer override | `observation_portal.accounts.serializers.AccountRemovalSerializer` |\n| | `SCIAPPLICATIONS_CALL_SERIALIZER` | Class dotpath for SciApplications's Call serializer override | `observation_portal.sciapplications.serializers.CallSerializer` |\n| | `SCIAPPLICATIONS_SCIENCEAPPLICATION_SERIALIZER` | Class dotpath for SciApplications's Science Application serializer override | `observation_portal.sciapplications.serializers.ScienceApplicationSerializer` |\n| as_dict Overrides | `OBSERVATIONS_SUMMARY_AS_DICT` | Class dotpath for Observation's Summary as_dict override | `observation_portal.observations.models.summary_as_dict` |\n| | `OBSERVATIONS_CONFIGURATIONSTATUS_AS_DICT` | Class dotpath for Observation's ConfigurationStatus as_dict override | `observation_portal.observations.models.configurationstatus_as_dict` |\n| | `OBSERVATIONS_OBSERVATION_AS_DICT` | Class dotpath for Observation's Observation as_dict override | `observation_portal.observations.models.observation_as_dict` |\n| | `REQUESTGROUPS_CONSTRAINTS_AS_DICT` | Class dotpath for RequestGroups's Constraints as_dict override | `observation_portal.requestgroups.models.constraints_as_dict` |\n| | `REQUESTGROUPS_REGIONOFINTEREST_AS_DICT` | Class dotpath for RequestGroups's Instrument Config ROI as_dict override | `observation_portal.requestgroups.models.regionofinterest_as_dict` |\n| | `REQUESTGROUPS_INSTRUMENTCONFIG_AS_DICT` | Class dotpath for RequestGroups's Instrument Config as_dict override | `observation_portal.requestgroups.models.instrumentconfig_as_dict` |\n| | `REQUESTGROUPS_ACQUISITIONCONFIG_AS_DICT` | Class dotpath for RequestGroups's Acquisition Config as_dict override | `observation_portal.requestgroups.models.acquisitionconfig_as_dict` |\n| | `REQUESTGROUPS_GUIDINGCONFIG_AS_DICT` | Class dotpath for RequestGroups's Guiding Config as_dict override | `observation_portal.requestgroups.models.guidingconfig_as_dict` |\n| | `REQUESTGROUPS_TARGET_AS_DICT` | Class dotpath for RequestGroups's Target as_dict override | `observation_portal.requestgroups.models.target_as_dict` |\n| | `REQUESTGROUPS_CONFIGURATION_AS_DICT` | Class dotpath for RequestGroups's Configuration as_dict override | `observation_portal.requestgroups.models.configuration_as_dict` |\n| | `REQUESTGROUPS_LOCATION_AS_DICT` | Class dotpath for RequestGroups's Location as_dict override | `observation_portal.requestgroups.models.location_as_dict` |\n| | `REQUESTGROUPS_WINDOW_AS_DICT` | Class dotpath for RequestGroups's Window as_dict override | `observation_portal.requestgroups.models.window_as_dict` |\n| | `REQUESTGROUPS_REQUEST_AS_DICT` | Class dotpath for RequestGroups's Request as_dict override | `observation_portal.requestgroups.models.request_as_dict` |\n| | `REQUESTGROUPS_REQUESTGROUP_AS_DICT` | Class dotpath for RequestGroups's RequestGroup as_dict override | `observation_portal.requestgroups.models.requestgroup_as_dict` |\n| | `PROPOSALS_PROPOSAL_AS_DICT` | Class dotpath for Proposal's Proposal as_dict override | `observation_portal.proposals.models.proposal_as_dict` |\n| | `PROPOSALS_TIMEALLOCATION_AS_DICT` | Class dotpath for Proposal's TimeAllocation as_dict override | `observation_portal.proposals.models.timeallocation_as_dict` |\n| | `PROPOSALS_MEMBERSHIP_AS_DICT` | Class dotpath for Proposal's Membership as_dict override | `observation_portal.proposals.models.membership_as_dict` |\n| duration Overrides | `INSTRUMENT_CONFIGURATION_PER_EXPOSURE_DURATION` | Class dotpath for duration_per_exposure method override | `observation_portal.requestgroups.duration_utils.get_instrument_configuration_duration_per_exposure` |\n\n\n## Local Development\n\n### **Set up external services**\n\nPlease refer to the [Configuration Database](https://github.com/observatorycontrolsystem/configdb) and [Downtime Database](https://github.com/observatorycontrolsystem/downtime) projects for instructions on how to get those running, as well as the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/install-elasticsearch.html) for options on how to run Elasticsearch.\n\n\n### **Poetry**\n\nWe use Poetry for package management. If you already have Poetry installed, you\ncan skip this section.\n\nYou can install Poetry using one of the many options listed at https://python-poetry.org/docs/#installation.\nOne simple option is using Pipx:\n\n python3 -m pip install --user pipx\n python3 -m pipx ensurepath\n pipx install poetry\n\n### **Install**\n\nInstall the project and its Python dependencies:\n\n poetry install\n\nThis will install the project in a Poetry managed virtual environment. To run\ncommands in that environment either use `poetry run ...` or start a shell in\nthat environment with `poetry shell`\n\n### **Set up the database**\n\nThis example uses the [PostgreSQL Docker image](https://hub.docker.com/_/postgres) to create a database. Make sure that the options that you use to set up your database correspond with your configured database settings.\n\n docker run --name observation-portal-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=observation_portal -v/var/lib/postgresql/data -p5432:5432 -d postgres:11.1\n\nAfter creating the database, migrations must be applied to set up the tables in the database.\n\n poetry run python manage.py migrate\n\n### **Run the tests**\n\n poetry run python manage.py test --settings=observation_portal.test_settings\n\n### **Run the portal**\n\n poetry run python manage.py runserver\n\nThe observation portal should now be accessible from <http://127.0.0.1:8000>!\n",
"bugtrack_url": null,
"license": "GPL-3.0-only",
"summary": "The Observatory Control System (OCS) Observation Portal django apps",
"version": "4.13.3",
"project_urls": {
"Homepage": "https://observatorycontrolsystem.github.io",
"Repository": "https://github.com/observatorycontrolsystem/observation-portal"
},
"split_keywords": [
"observations",
" astronomy",
" astrophysics",
" cosmology",
" science"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cbcd8ab9ecd4f6ce91903d39b0eb3f7e042fc9deb7443cd8c31f6beda3a8bb53",
"md5": "659dccf52b04984d958127e37aff7b6e",
"sha256": "3224e3e31ee02d128450fb47875c98639692ad49b65aa3cac36c27691cce4d68"
},
"downloads": -1,
"filename": "django_ocs_observation_portal-4.13.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "659dccf52b04984d958127e37aff7b6e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<3.11,>=3.8",
"size": 886901,
"upload_time": "2024-12-19T00:37:29",
"upload_time_iso_8601": "2024-12-19T00:37:29.553695Z",
"url": "https://files.pythonhosted.org/packages/cb/cd/8ab9ecd4f6ce91903d39b0eb3f7e042fc9deb7443cd8c31f6beda3a8bb53/django_ocs_observation_portal-4.13.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "aa05c4e3c2ab851bcf0a84a5b6ce12fd4148603d1b6a43094966faf3039cd5e0",
"md5": "572e6052d9dc0d04e68c673a360f1a54",
"sha256": "40be5321814e19f342d6c28d1f04548eb1175061f3f3526c16fe2e41e6aefde4"
},
"downloads": -1,
"filename": "django_ocs_observation_portal-4.13.3.tar.gz",
"has_sig": false,
"md5_digest": "572e6052d9dc0d04e68c673a360f1a54",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<3.11,>=3.8",
"size": 770747,
"upload_time": "2024-12-19T00:37:32",
"upload_time_iso_8601": "2024-12-19T00:37:32.949310Z",
"url": "https://files.pythonhosted.org/packages/aa/05/c4e3c2ab851bcf0a84a5b6ce12fd4148603d1b6a43094966faf3039cd5e0/django_ocs_observation_portal-4.13.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-19 00:37:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "observatorycontrolsystem",
"github_project": "observation-portal",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "django-ocs-observation-portal"
}