GithubHelp home page GithubHelp logo

city-of-helsinki / smbackend Goto Github PK

View Code? Open in Web Editor NEW
17.0 23.0 22.0 7.82 MB

Service Map backend

License: GNU Affero General Public License v3.0

Python 98.01% Shell 0.77% Dockerfile 0.24% Game Maker Language 0.97%

smbackend's Introduction

Build Status Codecov Quality Gate Status Code style: black

Service Map Backend

This is the backend service for the Service Map UI.

Installation with Docker Compose

First configure development environment settings as stated in config_dev.env.example and in config_dev_ui.env.example.

Running the application

Run application with docker-compose up

This will startup and bind local postgres, servicemap backend and servicemap frontend containers.

Importing data

To import data for development usage and automatically index it, run command: docker-compose run servicemap maintenance_tasks all

Installation without Docker

  1. First, install the necessary Debian packages.
  • libpython3.10-dev
  • python3.10-distutils
  • virtualenvwrapper
  • libyaml-dev
  • libxml2-dev
  • libxslt1-dev
  • voikko-fi
  • libvoikko-dev
  1. Clone the repository. Use pyenv to manage python version and create a virtualenv with virtualenvwrapper.
    The virtualenv that will be created and used here is named "servicemap"
pyenv install -v 3.10.1
pyenv virtualenv 3.10.1 smbackend
pyenv local smbackend
pyenv virtualenvwrapper
mkvirtualenv servicemap

Installation and usage info for pyenv, pyenv-virtualenvwrapper and
virtualenvwrapper can be found here: https://github.com/pyenv/pyenv-virtualenv https://github.com/pyenv/pyenv-virtualenvwrapper https://virtualenvwrapper.readthedocs.io/en/latest/install.html

  1. Install pip requirements. Be sure to load the virtualenv before installing the requirements: Example with virtualenv named servicemap as created in example above. workon servicemap Install the requirements: pip install -r requirements.txt

If this error occurs:

 ImportError: cannot import name 'html5lib' from 'pip._vendor' (/home/johndoe/.virtualenvs/servicemap/lib/python3.10/site-packages/pip/_vendor/__init__.py)

Try installing latest pip.

curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
  1. Setup the PostGIS database.

Please note, we recommend PostgreSQL version 13 or higher.

Local setup: First, ensure that the collation fi_FI.UTF-8 exists by entering the postgresql shell with the psql command.

sudo su postgres
psql
SELECT * FROM pg_collation where collname like '%fi%';

There should be a collname fi_FI.UTF-8 . If not, you must create the collation.

sudo su postgres
psql
ALTER database template1 is_template=false;
DROP database template1;
CREATE DATABASE template1 WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'fi_FI.UTF-8' LC_CTYPE = 'fi_FI.UTF-8' CONNECTION LIMIT = -1 TEMPLATE template0;
ALTER database template1 is_template=true;
\q  
psql template1 -c 'CREATE EXTENSION IF NOT EXISTS postgis;'
psql template1 -c 'CREATE EXTENSION IF NOT EXISTS hstore;'
psql template1 -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'
createuser -RSPd servicemap
createdb -O servicemap -T template1 -l fi_FI.UTF-8 -E utf8 servicemap
ERROR:  could not open extension control file "/usr/share/postgresql/14/extension/postgis.control": No such file or directory

Solution for ubuntu and Postgresql 14:

sudo apt install postgis postgresql-14-postgis-3

Docker setup (modify as needed, starts the database on local port 8765):

docker run --name servicemap-psql -e POSTGRES_USE.R=servicemap -e POSTGRES_PASSWORD=servicemap -p 8765:5432 -d mdillon/postgis
# you'll need the hstore extension enabled:
echo "CREATE EXTENSION hstore;" | docker exec -i servicemap-psql psql -U servicemap
  1. Create database tables.
./manage.py migrate

If this command fails with: django.core.exceptions.ImproperlyConfigured: GEOS is required and has not been detected., then install the GEOS library. On a Mac this can be achieved with HomeBrew:

brew install geos
  1. Import geo data.
./manage.py geo_import finland --municipalities
./manage.py geo_import helsinki --divisions
./manage.py geo_import helsinki --addresses

Importing addresses from geo-search

./manage.py geo_import uusimaa --addresses
./manage.py update_postal_code_areas

Note, this imports all the addresses from Uusimaa-region and might take ~6 hours. Postal code area datas can be enriched from geo-search using update_postal_code_areas -management-command.

Indexing search columns

The search columns must be indexed after the first time data is imported or geo-search addresses are imported or addresses are enriched with geo-search data.

./manage.py index_search_columns
  1. Redis Redis is used for caching and as a message broker for Celery. Install Redis. Ubuntu: sudo apt-get install redis-server

  2. Celery

Install and run a message broker such as Redis or RabbitMQ. Redis is recommended as it is also used for caching. Configure the message broker in the environment variable "CELERY_BROKER_URL". Start a Celery worker to handle asynchronous tasks locally with command:

celery -A smbackend worker -l INFO

Note, in production environment the celery worker can be run as a daemon. https://docs.celeryproject.org/en/stable/userguide/daemonizing.html#daemonizing Start Celery beat to handle scheduled periodic tasks with command:

celery -A smbackend beat -l INFO

Observations

Load the initial observation data with the command:

./scripts/import_observation_initial_data.sh

Troubleshooting

The error:

OSError: dlopen(/usr/local/lib/libgdal.dylib, 6): Symbol not found: _GEOSArea

Can be fixed by adding this to local_settings.py:

GDAL_LIBRARY_PATH = "/usr/local/lib/libgdal.dylib"
import ctypes
ctypes.CDLL(GDAL_LIBRARY_PATH)

The error:

 psycopg2.errors.UndefinedObject: operator class "gin_trgm_ops" does not exist for access method "gin"

Can be fixed by adding the pg_trgm extension to the database:

psql template1 -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'

smbackend's People

Contributors

arj-peshtani avatar azf avatar dependabot[bot] avatar frodotus avatar genie9 avatar halarotu avatar japauliina avatar jukvalim avatar jussiarpalahti avatar juyrjola avatar lorand-ibm avatar luopio avatar mhieta avatar op-lamminen avatar pjlampil avatar quvide avatar rikuoja avatar seitztimo avatar tituomin avatar vikoivun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smbackend's Issues

django-haystack 2.3.1 failed because of logging failure

Updated to django-haystack==2.3.1.
It uses elasticsearch==1.3.0 instead of pyelasticsearch.

However, elasticsearch caused an exception because it tried to log requests and failed. [see 1]

I fixed this (temporarily?) by explicitly setting the null log handler to the elasticsearch logger in local_settings. [see 2] Didn't figure out the actual problem causing this. (Shouldn't the global handler handle this?)

Stacktrace [1]:

ValueError: I/O operation on closed file.                                                                                                smbacke+ 25605  0.0  4.1 477452 167756 ?       S    Feb05   0:25 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
Traceback (most recent call last):                                                                                                       i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/django/core/handlers/base.py", line 111, in get_response         smbacke+ 31944  0.0  4.0 473828 162964 ?       S    Feb05   0:16 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    response = wrapped_callback(request, *callback_args, **callback_kwargs)                                                              i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/rest_framework/viewsets.py", line 78, in view                    root@servicemap:~# kill -HUP 31944
    return self.dispatch(request, *args, **kwargs)                                                                                       root@servicemap:~# ps aux |egrep uwsgi|egrep smback
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view       smbacke+  1961  0.0  4.0 473060 162212 ?       S    Feb05   0:17 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    return view_func(*args, **kwargs)                                                                                                    i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/rest_framework/views.py", line 400, in dispatch                  smbacke+ 10321  0.0  1.1 342376 45316 ?        S    Jan13   2:30 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    response = self.handle_exception(exc)                                                                                                i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/rest_framework/views.py", line 397, in dispatch                  smbacke+ 25603  0.0  3.9 472268 161212 ?       S    Feb05   0:22 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    response = handler(request, *args, **kwargs)                                                                                         i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "./services/api.py", line 458, in list                                                                                            smbacke+ 25605  0.0  4.1 477452 167756 ?       S    Feb05   0:25 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    page = self.paginate_queryset(self.object_list)                                                                                      i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/rest_framework/generics.py", line 151, in paginate_queryset      smbacke+ 28803  0.0  0.7 342376 32384 ?        S    11:48   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    page_number = paginator.validate_number(page)                                                                                        i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/django/core/paginator.py", line 39, in validate_number           root@servicemap:~# kill -HUP 1961
    if number > self.num_pages:                                                                                                          root@servicemap:~# ps aux |egrep uwsgi|egrep smback
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/django/core/paginator.py", line 86, in _get_num_pages            smbacke+ 10321  0.0  1.1 342376 45316 ?        S    Jan13   2:30 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    if self.count == 0 and not self.allow_empty_first_page:                                                                              i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/django/core/paginator.py", line 72, in _get_count                smbacke+ 25603  0.0  3.9 472268 161212 ?       S    Feb05   0:22 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    self._count = self.object_list.count()                                                                                               i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/query.py", line 480, in count                           smbacke+ 25605  0.0  4.1 477452 167756 ?       S    Feb05   0:25 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    return len(self)                                                                                                                     i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/query.py", line 91, in __len__                          smbacke+ 28803  0.0  0.7 342376 32384 ?        S    11:48   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    self._result_count = self.query.get_count()                                                                                          i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/backends/__init__.py", line 625, in get_count           smbacke+ 28807  0.0  0.7 342376 32384 ?        S    11:48   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    self.run()                                                                                                                           i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/backends/elasticsearch_backend.py", line 918, in run    root@servicemap:~# kill -HUP 10321
                                                                                                                                         root@servicemap:~# kill -HUP 25603
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/backends/__init__.py", line 34, in wrapper              bash: kill: (25603) - No such process
    return func(obj, query_string, *args, **kwargs)                                                                                      root@servicemap:~# kill -HUP 25605
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/haystack/backends/elasticsearch_backend.py", line 493, in search bash: kill: (25605) - No such process
    }                                                                                                                                    root@servicemap:~# ps aux |egrep uwsgi|egrep smback
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/elasticsearch/client/utils.py", line 68, in _wrapped             smbacke+ 10321  0.0  1.1 342380 46112 ?        S    Jan13   2:31 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    return func(*args, params=params, **kwargs)                                                                                          i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/elasticsearch/client/__init__.py", line 498, in search           smbacke+ 28867  0.0  0.8 342380 32420 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    params=params, body=body)                                                                                                            i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/elasticsearch/transport.py", line 301, in perform_request        smbacke+ 28868  0.0  0.8 342380 32420 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    status, headers, data = connection.perform_request(method, url, params, body, ignore=ignore, timeout=timeout)                        i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/elasticsearch/connection/http_urllib3.py", line 85, in perform_r smbacke+ 28869  0.0  0.8 342380 32420 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
equest                                                                                                                                   i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
    raw_data, duration)                                                                                                                  smbacke+ 28870  0.0  0.8 342380 32420 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
  File "/home/smbackend/.virtualenvs/smvenv/lib/python3.4/site-packages/elasticsearch/connection/base.py", line 62, in log_request_succe i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
ss                                                                                                                                       root@servicemap:~# kill -HUP 10321
    status_code, duration                                                                                                                root@servicemap:~# ps aux |egrep uwsgi|egrep smback
  File "/usr/lib/python3.4/logging/__init__.py", line 1260, in info                                                                      smbacke+ 10321  0.0  0.3  94984 15316 ?        R    Jan13   2:31 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
    self._log(INFO, msg, args, **kwargs)                                                                                                 i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
  File "/usr/lib/python3.4/logging/__init__.py", line 1395, in _log                                                                      root@servicemap:~# ps aux |egrep uwsgi|egrep smback
    self.handle(record)                                                                                                                  smbacke+ 10321  0.0  1.1 342392 46076 ?        S    Jan13   2:32 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
  File "/usr/lib/python3.4/logging/__init__.py", line 1405, in handle                                                                    i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
    self.callHandlers(record)                                                                                                            smbacke+ 28883  0.0  0.8 342392 32408 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
  File "/usr/lib/python3.4/logging/__init__.py", line 1467, in callHandlers                                                              i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
    hdlr.handle(record)                                                                                                                  smbacke+ 28884  0.0  0.8 342392 32408 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
  File "/usr/lib/python3.4/logging/__init__.py", line 839, in handle                                                                     i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
    self.emit(record)                                                                                                                    smbacke+ 28885  0.0  0.8 342392 32408 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
  File "/usr/lib/python3.4/logging/handlers.py", line 464, in emit                                                                       i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log
    self.stream.flush()                                                                                                                  smbacke+ 28886  0.0  0.8 342392 32408 ?        S    11:49   0:00 /usr/bin/uwsgi --ini /usr/share/uwsgi/conf/default.ini --yaml /etc/uwsg
ValueError: I/O operation on closed file.                                                                                                i/apps-enabled/smbackend.yml --daemonize /var/log/uwsgi/app/smbackend.log

local_settings.py [2]:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'handlers': {
        # Include the default Django email handler for errors
        # This is what you'd get without configuring logging at all.
        'mail_admins': {
            'class': 'django.utils.log.AdminEmailHandler',
            'level': 'ERROR',
             # But the emails are plain text by default - HTML is nicer
            'include_html': True,
        },
        # Log to a text file that can be rotated by logrotate
        'logfile': {
            'class': 'logging.handlers.WatchedFileHandler',
            'filename': '/var/log/django/smbackend.log'
        },
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
    },
    'loggers': {
        # Again, default Django configuration to email unhandled exceptions
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        # Might as well log any errors anywhere else in Django
        'django': {
            'handlers': ['logfile'],
            'level': 'WARNING',
            'propagate': False,
        },
        'elasticsearch': {
            'handlers': ['null'],
            'level': 'DEBUG',
            'propagate': False,
        },
        '': {
            'handlers': ['logfile'],
            'level': 'INFO',
            'propagate': True,
        },
    },
}

Don't index descriptions for statues?

Statues & works of art often match queries because their descriptions contain numerous references to people & places. Make ignorable fields configurable.

Search parameter "only" no longer working

I can't seem to restrict the fields returned by API search query. For example the following query returns also other fields than just name and street_address:

https://api.hel.fi/servicemap/v2/search/?q=leikkipuisto&only=unit.name,unit.street_address

Additionally, the documentation for the API seems to be partially incomplete. (Yes, I know this site is no longer in use but there seems to be no alternative either.) The description for only parameter ends abruptly

"Restrict the field returned in the results. Separate field names by commas. In the search endpoint, you must qualify the field names with the resource names using the format"

Maybe this should include similar instructions as the include parameter above?

For example, instead of include=department you must specify include=unit.department.

Implement set theory supporting filtering of units

Currently units are filtered by giving a list of services, e.g. unit?service=2123,12321

The new version supports more complex relationships through ontologies. Thus we should support something like unit?serviceunit=(124*232+21*33)

Also see #48

Support for v4 of TPR API

Plan of action

  • to be built in a separate branch (tpr-v4)
  • implement new models and serializers in new files that extend v3
  • endpoint at v2/ (thus external version number will be 2), with v1/ remaining as is
  • update scripts to run side-by-side until EOL of TPR v3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.