{"id":13501272,"url":"https://github.com/hartwork/jawanndenn","last_synced_at":"2025-05-16T04:07:24.178Z","repository":{"id":37851353,"uuid":"71672844","full_name":"hartwork/jawanndenn","owner":"hartwork","description":":date: Simple alternative to Doodle polls and scheduling (Python 3, Django 5, some JavaScript)","archived":false,"fork":false,"pushed_at":"2025-05-08T20:15:15.000Z","size":7976,"stargazers_count":190,"open_issues_count":15,"forks_count":25,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-08T21:26:10.571Z","etag":null,"topics":["django","django-application","django-framework","django5","docker","docker-compose","doodle","doodle-like","javascript","material-design","materializecss","python","python3"],"latest_commit_sha":null,"homepage":"https://jawanndenn.de/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hartwork.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-10-23T00:15:50.000Z","updated_at":"2025-05-08T20:15:13.000Z","dependencies_parsed_at":"2024-01-05T18:28:54.669Z","dependency_job_id":"6dce2da6-8715-446c-9ec2-199864e30b1e","html_url":"https://github.com/hartwork/jawanndenn","commit_stats":{"total_commits":1577,"total_committers":7,"mean_commits":"225.28571428571428","dds":0.3272035510462904,"last_synced_commit":"1f6cd72e927ef3cccd3e2e6fc9b0803e970d83e2"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hartwork%2Fjawanndenn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hartwork%2Fjawanndenn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hartwork%2Fjawanndenn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hartwork%2Fjawanndenn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hartwork","download_url":"https://codeload.github.com/hartwork/jawanndenn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464897,"owners_count":22075571,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","django-application","django-framework","django5","docker","docker-compose","doodle","doodle-like","javascript","material-design","materializecss","python","python3"],"created_at":"2024-07-31T22:01:31.239Z","updated_at":"2025-05-16T04:07:19.169Z","avatar_url":"https://github.com/hartwork.png","language":"Python","readme":".. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n.. image:: https://github.com/hartwork/jawanndenn/workflows/Build%20and%20test%20using%20Docker/badge.svg\n    :target: https://github.com/hartwork/jawanndenn/actions\n\n\nWhat is jawanndenn?\n===================\n\n.. figure:: https://raw.githubusercontent.com/hartwork/jawanndenn/master/jawanndenn-setup.png\n   :alt: Screenshot of poll creation in jawanndenn\n\n*jawanndenn* is a simple web application to schedule meetings and run\npolls, a libre alternative to Doodle.  It is using the following technology:\n\n- Python\n    - `Docker Compose`_\n    - `Django`_\n        - `Django Extensions`_\n        - `Django Ratelimit`_ + `msgpack-python`_\n        - `django-redis`_\n        - `Django REST framework`_\n        - `Factory Boy`_\n    - `Gunicorn`_ + `gunicorn-color-logger`_\n    - `parameterized`_\n    - `pre-commit`_\n    - `python-rapidjson`_\n    - `sentry-python`_\n    - `wait-for-it`_\n\n- JavaScript / CSS / Fonts\n    - `Google Webfonts Helper`_\n    - `jQuery`_\n    - `jQuery noty`_\n    - `Materialize`_\n    - `Roboto`_\n\n- Storage\n    - `PostgreSQL`_\n    - `Redis`_\n    - `SQLite`_\n\n- Scheduling\n    - `Supercronic`_\n\n*jawanndenn* is `libre software`_ developed by `Sebastian Pipping`_. The\nserver code is licensed under the `GNU Affero GPL license`_ version 3\nor later whereas the client code is licensed under the `GNU GPL\nlicense`_ version 3 or later.\n\nPlease `report bugs`_ and let me know if you `like`_ it.\n\n\nPoll Setup Format\n=================\n\nThe textarea titled \"Setup (JSON)\" uses\na simple `JSON`_-based format that knows the following keys:\n\n- ``equal_width`` — a bool to control whether all options are pumped up\n  to the same width (``true`` or ``false``) to counter potential voter bias\n- ``lifetime`` — duration after which this poll will be deleted;\n  can be ``\"week\"`` or ``\"month\"``; an enum-like string\n- ``options`` — a list of strings, one for each option;\n  supports `Markdown`_-like syntax for: bold, italic, inline code\n- ``title`` — the title or headline of the poll to run;\n  supports `Markdown`_-like syntax for: bold, italic, inline code\n\n\nInstallation\n============\n\nTo install the latest release without cloning the Git repository:\n\n::\n\n    # pip3 install jawanndenn --user\n\nTo install from a Git clone:\n\n::\n\n    # ./setup.py install --user\n\n\nDeployment with docker-compose\n==============================\n\nCreate a simple file ``.env`` like this one:\n\n::\n\n    JAWANNDENN_POSTGRES_NAME=jawanndenn\n    JAWANNDENN_POSTGRES_USER=jawanndenn\n    JAWANNDENN_POSTGRES_PASSWORD=dEb2PIcinemA8poH\n    JAWANNDENN_SECRET_KEY=606ea88f183a27919d5c27ec7f948906d23fdd7821684eb59e8bcf7377e3853b\n\nMake sure to **adjust these values** after copy and paste!\n\nYou can then build and run a docker image using ``docker-compose up --build``.\n\nThe app is served on ``localhost:54080``.\nPostgreSQL data is saved to ``~/.jawanndenn-docker-pgdata/`` on the host system.\nThere is also an instance of Redis used for cross-process rate limiting,\nand a \"cron\" housekeeping container that will go delete polls that have exceeded their\nconfigured lifetime, every 60 minutes.\n\n(If you need a low-maintenance SSL reverse proxy in front of jawanndenn,\n`docker-ssl-reverse-proxy \u003chttps://github.com/hartwork/docker-ssl-reverse-proxy\u003e`_\ncould be of interest.)\n\nThere is a few more environment variables that you could want to adjust in your environment.\nAltogether, there are these variables:\n\n\nEnvironment variables\n---------------------\n\n``DJANGO_SETTINGS_MODULE``\n~~~~~~~~~~~~~~~~~~~~~~~~~~\nDjango settings module to use, leave as is, defaults to ``jawanndenn.settings``\n(see ``docker-compose.yml``)\n\n\n``JAWANNDENN_ALLOWED_HOSTS``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nHostnames to serve jawanndenn at, list separated by comma,\nis set to ``jawanndenn.de,www.jawanndenn.de`` on the main production server,\ndefaults to ``127.0.0.1,0.0.0.0,localhost``\n(see ``jawanndenn/settings.py``)\n\n\n``JAWANNDENN_DEBUG``\n~~~~~~~~~~~~~~~~~~~~\nDebug mode, disabled for all values but ``True``, disabled by default,\nshould never be enabled in production for security\n(see ``jawanndenn/settings.py``)\n\n\n``JAWANNDENN_MAX_POLLS``\n~~~~~~~~~~~~~~~~~~~~~~~~\nMaximum total number of polls to store, denial of service protection,\ndefaults to ``1000``\n(see ``jawanndenn/settings.py`` and ``docker-compose.yml``)\n\n\n``JAWANNDENN_MAX_VOTES_PER_POLL``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nMaximum total number of polls to store, denial of service protection,\ndefaults to ``40``\n(see ``jawanndenn/settings.py``)\n\n\n``JAWANNDENN_POSTGRES_HOST``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nHostname of the PostgreSQL database to connect to; defaults to ``postgres``\n(see ``docker-compose.yml``)\n\n\n``JAWANNDENN_POSTGRES_NAME``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nDatabase name of the PostgreSQL database to connect to;\nno default, always required\n\n\n``JAWANNDENN_POSTGRES_PASSWORD``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nPassword for log-in with the PostgreSQL database;\nno default, always required\n\n\n``JAWANNDENN_POSTGRES_PORT``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nPort of the PostgreSQL database to connect to; defaults to ``5432``\n(see ``docker-compose.yml``)\n\n\n``JAWANNDENN_POSTGRES_USER``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nUsername for log-in with the PostgreSQL database;\nno default, always required\n\n\n``JAWANNDENN_REDIS_HOST``\n~~~~~~~~~~~~~~~~~~~~~~~~~\nHostname of the Redis database to connect to; defaults to ``redis``\n(see ``docker-compose.yml``)\n\n\n``JAWANNDENN_REDIS_PORT``\n~~~~~~~~~~~~~~~~~~~~~~~~~\nPort of the Redis database to connect to; defaults to ``6379``\n(see ``docker-compose.yml``)\n\n\n``JAWANNDENN_SECRET_KEY``\n~~~~~~~~~~~~~~~~~~~~~~~~~\n`Django secret key \u003chttps://docs.djangoproject.com/en/4.0/ref/settings/#secret-key\u003e`_;\nshould be long, generated, not used elsewhere; no default, always required\n\n\n``JAWANNDENN_SENTRY_DSN``\n~~~~~~~~~~~~~~~~~~~~~~~~~\n`Data source name (DSN) \u003chttps://docs.sentry.io/product/sentry-basics/dsn-explainer/\u003e`_\nfor use with `Sentry \u003chttps://sentry.io/\u003e`_, disabled/empty by default\n(see ``jawanndenn/settings.py``)\n\n\n``JAWANNDENN_URL_PREFIX``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nPrefix string to insert into URLs rather after the domain name\nto help with hosting multiple apps under the same domain side by side;\ne.g. prefix ``prefix123`` will result in URLs like ``https://\u003cdomain\u003e/prefix123/poll/\u003cid\u003e``;\nempty by default\n(see ``jawanndenn/settings.py``)\n\n\nCommand line usage\n==================\n\nWhen installed, invocation is as simple as\n\n::\n\n    # jawanndenn\n\nDuring development, you may want to run *jawanndenn* from the Git clone\nusing\n\n::\n\n    # PYTHONPATH=. python3 -m jawanndenn --debug\n\nCurrently supported arguments are:\n\n::\n\n    # jawanndenn --help\n    usage: jawanndenn [-h] [--debug] [--host HOST] [--port PORT]\n                      [--url-prefix PATH] [--database-sqlite3 FILE]\n                      [--django-secret-key-file FILE] [--max-polls COUNT]\n                      [--max-votes-per-poll COUNT] [--dumpdata]\n                      [--loaddata FILE.json]\n\n    optional arguments:\n      -h, --help            show this help message and exit\n      --debug               Enable debug mode (default: disabled)\n      --host HOST           Hostname or IP address to listen at (default:\n                            127.0.0.1)\n      --port PORT           Port to listen at (default: 8080)\n      --url-prefix PATH     Path to prepend to URLs (default: \"\")\n      --database-sqlite3 FILE\n                            File to write the database to (default:\n                            ~/jawanndenn.sqlite3)\n      --django-secret-key-file FILE\n                            File to use for Django secret key data (default:\n                            ~/jawanndenn.secret_key)\n\n    limit configuration:\n      --max-polls COUNT     Maximum number of polls total (default: 1000)\n      --max-votes-per-poll COUNT\n                            Maximum number of votes per poll (default: 40)\n\n    data import/export arguments:\n      --dumpdata            Dump a JSON export of the database to standard output,\n                            then quit.\n      --loaddata FILE.json  Load a JSON export of the database from FILE.json,\n                            then quit.\n\n\nMigrating data from jawanndenn 1.x to 2.x\n=========================================\n\nMigration takes four steps:\n\n1. Update to the latest version of jawanndenn 1.x, e.g. by running:\n   ``pip2 install --upgrade 'jawanndenn\u003c2'``;\n   the JSON data export was first introduced with release 1.6.3.\n\n2. Export existing polls:\n\n   a) If you're using the commend line app:\n      ``python2 -m jawanndenn --dumpdata \u003e dump.json``\n\n   b) If you're using docker-compose:\n      ``docker-compose run -T jawanndenn --database-pickle /data/polls.pickle --dumpdata \u003e dump.json``\n\n3. Deploy latest jawanndenn 2.x somewhere (as described above) or just\n   ``pip3 install 'jawanndenn\u003e=2'``\n   it somewhere\n\n4. Import the JSON dump created in step (2):\n\n   a) If you're using the commend line app:\n      ``python3 -m jawanndenn --loaddata dump.json``\n\n   b) If you're using docker-compose:\n      ``docker-compose run -T jawanndenn sh -c 'cat \u003e /tmp/dump.json \u0026\u0026 DJANGO_SETTINGS_MODULE=jawanndenn.settings python3 -m django loaddata /tmp/dump.json' \u003c dump.json``\n\n\nGoals\n=====\n\n-  Libre software to host yourself, unlike Doodle\n-  More simplistic, sexy and/or fun than `libre alternatives`_, in alphabetic order:\n\n   -  `Bitpoll`_ (ex. `Dudel`_)\n   -  `Crab Fit`_\n   -  `Croodle`_\n   -  `Dudle`_\n   -  (`Drupal Date picker formatter`_)\n   -  (`Foodle`_ (discontinued; `on GitHub`_, ex. `DFN scheduler`_, ex. `DFN Terminplaner+`_))\n   -  `Framadata`_ (`Sources`_, ex. `OpenSondage`_, ex. `STUdS`_)\n   -  `Nextcloud Polls`_\n   -  `Noodle`_\n   -  `Nuages`_\n   -  `Pleft`_\n   -  `Rallly`_\n   -  `RDVz`_\n   -  `sowhenthen`_\n   -  `VoteOn.Date`_\n\n-  Keep things simple, usable, maintainable\n-  Support invocation from the command line, e.g. for spontaneous polls in a LAN\n-  Have security in mind\n\nPlease check out the `list of upcoming features`_.\n\n\nNon-goals\n=========\n\n-  Use of heavy frontend frameworks: building blocks only\n-  Read availability from calendars\n\n\nThanks\n======\n\nSpecial thanks to Arne Maier (`@KordonDev`_) for reporting\nan XSS vulnerability, responsibly.\n\n\n.. _Python: https://www.python.org/\n.. _Docker Compose: https://docs.docker.com/compose/\n.. _Django: https://www.djangoproject.com/\n.. _Django Extensions: https://github.com/django-extensions/django-extensions\n.. _Django Ratelimit: https://github.com/jsocol/django-ratelimit\n.. _msgpack-python: https://github.com/msgpack/msgpack-python\n.. _django-redis: https://github.com/niwinz/django-redis\n.. _Django REST framework: https://www.django-rest-framework.org/\n.. _Factory Boy: https://factoryboy.readthedocs.io/en/latest/\n.. _Gunicorn: https://gunicorn.org/\n.. _gunicorn-color-logger: https://github.com/swistakm/gunicorn-color-logger\n.. _parameterized: https://github.com/wolever/parameterized\n.. _pre-commit: https://pre-commit.com/\n.. _python-rapidjson: https://github.com/python-rapidjson/python-rapidjson\n.. _sentry-python: https://github.com/getsentry/sentry-python\n.. _wait-for-it: https://github.com/clarketm/wait-for-it\n.. _Google Webfonts Helper: https://google-webfonts-helper.herokuapp.com/\n.. _jQuery: http://jquery.com/\n.. _jQuery noty: http://ned.im/noty/#/about\n.. _Materialize: http://materializecss.com/\n.. _Roboto: https://fonts.google.com/specimen/Roboto\n.. _PostgreSQL: https://www.postgresql.org/\n.. _Redis: https://redis.io/\n.. _SQLite: https://www.sqlite.org/index.html\n.. _Supercronic: https://github.com/aptible/supercronic\n.. _libre software: https://www.gnu.org/philosophy/free-sw.en.html\n.. _Sebastian Pipping: https://blog.hartwork.org/\n.. _GNU Affero GPL license: https://www.gnu.org/licenses/agpl.en.html\n.. _GNU GPL license: https://www.gnu.org/licenses/gpl.html\n.. _report bugs: https://github.com/hartwork/jawanndenn/issues\n.. _like: mailto:sebastian@pipping.org\n.. _JSON: https://www.json.org/\n.. _Markdown: https://commonmark.org/help/\n.. _the related documentation of Django: https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/modwsgi/\n.. _file a support ticket: https://github.com/hartwork/jawanndenn/issues/new\n.. _drop me a mail: mailto:sebastian@pipping.org\n.. _libre alternatives: http://alternativeto.net/software/doodle/?license=opensource\n.. _Bitpoll: https://github.com/fsinfuhh/Bitpoll\n.. _Crab Fit: https://github.com/GRA0007/crab.fit\n.. _Croodle: https://github.com/jelhan/croodle\n.. _Dudel: https://github.com/opatut/dudel\n.. _Pleft: https://github.com/sander/pleft\n.. _Framadata: https://framadate.org/\n.. _Sources: https://git.framasoft.org/framasoft/framadate\n.. _OpenSondage: https://github.com/leblanc-simon/OpenSondage\n.. _STUdS: http://studs.unistra.fr/\n.. _Foodle: https://foodl.org/\n.. _on GitHub: https://github.com/UNINETT/Foodle\n.. _DFN scheduler: https://terminplaner.dfn.de/\n.. _DFN Terminplaner+: https://terminplaner2.dfn.de/\n.. _Dudle: https://dudle.inf.tu-dresden.de/\n.. _Nuages: https://nuages.domainepublic.net/\n.. _RDVz: https://sourceforge.net/projects/rdvz/\n.. _sowhenthen: https://github.com/kiyutink/sowhenthen\n.. _VoteOn.Date: https://gitlab.com/Glitchy-Tozier/voteon.date\n.. _Drupal Date picker formatter: http://alternativeto.net/software/date-picker-formatter-dudel-for-drupal/?license=opensource\n.. _Nextcloud Polls: https://github.com/nextcloud/polls\n.. _Noodle: https://github.com/kmerz/noodle\n.. _Rallly: https://github.com/lukevella/Rallly\n.. _list of upcoming features: https://github.com/hartwork/jawanndenn/issues/created_by/hartwork\n.. _@KordonDev: https://github.com/KordonDev\n","funding_links":[],"categories":["Python","docker"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhartwork%2Fjawanndenn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhartwork%2Fjawanndenn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhartwork%2Fjawanndenn/lists"}