Merge branch 'django-v4' into 'develop'

Draft: Django v4

See merge request sahkoinsinoorikilta/vtmk/web2.0-backend!72
This commit is contained in:
Ilari Ojakorpi
2022-12-25 13:10:34 +00:00
31 changed files with 1057 additions and 663 deletions
-4
View File
@@ -1,9 +1,5 @@
[report] [report]
show_missing = True show_missing = True
omit =
*/migrations/*
*/admin.py
*/translation.py
[run] [run]
omit = omit =
*/migrations/* */migrations/*
+2 -2
View File
@@ -26,7 +26,7 @@ audit:
- pushes - pushes
needs: [] needs: []
before_script: before_script:
- pip install poetry==1.1.13 - pip install poetry==1.3.1
- poetry config virtualenvs.create false - poetry config virtualenvs.create false
- poetry install --no-interaction --no-ansi - poetry install --no-interaction --no-ansi
script: script:
@@ -47,7 +47,7 @@ test:
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB" DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
DB_HOST: postgres DB_HOST: postgres
before_script: before_script:
- pip install poetry==1.1.13 - pip install poetry==1.3.1
- poetry config virtualenvs.create false - poetry config virtualenvs.create false
- poetry install --no-interaction --no-ansi - poetry install --no-interaction --no-ansi
script: script:
+1 -1
View File
@@ -2,7 +2,7 @@ FROM python:3.9-slim-buster as builder
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1
COPY . ./ COPY . ./
ENV POETRY_VERSION=1.1.13 ENV POETRY_VERSION=1.3.1
RUN pip install "poetry==$POETRY_VERSION" RUN pip install "poetry==$POETRY_VERSION"
RUN poetry export --without-hashes > requirements.txt RUN poetry export --without-hashes > requirements.txt
+6 -6
View File
@@ -2,11 +2,11 @@
[Django](https://www.djangoproject.com/) backend containing multiple small applications and api for Next.js frontend. [Django](https://www.djangoproject.com/) backend containing multiple small applications and api for Next.js frontend.
* **Web app:** Backend for the main website. * **Web app:** Backend for the main website.
* **Member register:** Data table app for viewing and modifying the member register, member applications and membership payments. * **Member register:** Data table app for viewing and modifying the member register, member applications and membership payments.
* **Kaehmy:** Form for creating and listing kaehmys * **Kaehmy:** Form for creating and listing kaehmys
* **Ohlhafv:** Form for creating and listing ohlhafv challenges. * **Ohlhafv:** Form for creating and listing ohlhafv challenges.
* **Infoscreen:** Angular-based slideshow app for the guild room's screens. * **Infoscreen:** Angular-based slideshow app for the guild room's screens.
## Installation ## Installation
Set up your SSH key authentication in GitLab Profile Settings. Then clone the repository and checkout the development branch: Set up your SSH key authentication in GitLab Profile Settings. Then clone the repository and checkout the development branch:
@@ -29,7 +29,7 @@ For depedencies and virtual environment, we use [poetry](https://python-poetry.o
First install [python](https://wiki.python.org/moin/BeginnersGuide/Download). Then install poetry: First install [python](https://wiki.python.org/moin/BeginnersGuide/Download). Then install poetry:
```bash ```bash
python3 -m pip install poetry python3 -m pip install poetry==1.3.1
``` ```
The easiest integration with VSCode is to have poetry install virtual environment in project folder, configured with CMD The easiest integration with VSCode is to have poetry install virtual environment in project folder, configured with CMD
+1 -1
View File
@@ -7,7 +7,7 @@ from django import forms
from django.utils import timezone from django.utils import timezone
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
class InfoItem(models.Model): class InfoItem(models.Model):
+23 -23
View File
@@ -1,6 +1,6 @@
"""File containing infoscreen urls.""" """File containing infoscreen urls."""
from django.conf.urls import url from django.urls import re_path
from django.conf import settings from django.conf import settings
from infoscreen.views import index from infoscreen.views import index
@@ -27,28 +27,28 @@ from infoscreen.views import createApyItem
from infoscreen.views import get_apy_json from infoscreen.views import get_apy_json
urlpatterns = [ urlpatterns = [
url(r"^$", default), re_path(r"^$", default),
url(r"^admin$", admin), re_path(r"^admin$", admin),
url(r"^(?P<idx>\d+)$", index), re_path(r"^(?P<idx>\d+)$", index),
url(r"^items$", info_items), re_path(r"^items$", info_items),
url(r"^rotation/(?P<idx>\d+)$", rotation), re_path(r"^rotation/(?P<idx>\d+)$", rotation),
url(r"^rotations$", rotations), re_path(r"^rotations$", rotations),
url(r"^instance$", createInstance), re_path(r"^instance$", createInstance),
url(r"^instance/(?P<idx>\d+)$", deleteInstance), re_path(r"^instance/(?P<idx>\d+)$", deleteInstance),
url(r"^types$", info_types), re_path(r"^types$", info_types),
url(r"^delete_item/(?P<type_id>\d+)/(?P<idx>\d+)$", delete_info_item), re_path(r"^delete_item/(?P<type_id>\d+)/(?P<idx>\d+)$", delete_info_item),
url(r"^create_external_image$", createExternalImageInfoItem), re_path(r"^create_external_image$", createExternalImageInfoItem),
url(r"^create_image$", create_image_item), re_path(r"^create_image$", create_image_item),
url(r"^create_video$", create_video_item), re_path(r"^create_video$", create_video_item),
url(r"^create_abbitem$", createABBItem), re_path(r"^create_abbitem$", createABBItem),
url(r"^create_sossoitem$", createSossoItem), re_path(r"^create_sossoitem$", createSossoItem),
url(r"^create_lunchitem$", createLunchItem), re_path(r"^create_lunchitem$", createLunchItem),
url(r"^create_eventitem$", createEventItem), re_path(r"^create_eventitem$", createEventItem),
url(r"^create_apyitem$", createApyItem), re_path(r"^create_apyitem$", createApyItem),
url(r"^create_websiteitem$", createExternalWebsiteItem), re_path(r"^create_websiteitem$", createExternalWebsiteItem),
url(r"^create_rotation$", create_rotation), re_path(r"^create_rotation$", create_rotation),
url(r"^delete_rotation/(?P<id>\d+)$", delete_rotation), re_path(r"^delete_rotation/(?P<id>\d+)$", delete_rotation),
url(r"^apyjson", get_apy_json), re_path(r"^apyjson", get_apy_json),
] ]
if settings.DEBUG: if settings.DEBUG:
+1 -1
View File
@@ -1,5 +1,5 @@
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from kaehmy.models import PresetRole, CustomRole, Application, Comment, BaseRole from kaehmy.models import PresetRole, CustomRole, Application, Comment, BaseRole
+1 -1
View File
@@ -1,6 +1,6 @@
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
VERBOSE_NAME = _("Kaehmy") VERBOSE_NAME = _("Kaehmy")
+1 -1
View File
@@ -1,6 +1,6 @@
import django_tables2 as tables import django_tables2 as tables
from django.db.models import Count, Q from django.db.models import Count, Q
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from kaehmy.models import Application from kaehmy.models import Application
+8 -8
View File
@@ -1,8 +1,8 @@
"""Kaehmy urls.""" """Kaehmy urls."""
from django.conf.urls import url from django.urls import re_path
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from kaehmy.views import view from kaehmy.views import view
from kaehmy.views import list_view from kaehmy.views import list_view
@@ -13,12 +13,12 @@ from kaehmy.views import export_view
urlpatterns = [ urlpatterns = [
# kaehmy # kaehmy
url(r"^new", view), re_path(r"^new", view),
url(r"^submit", submit), re_path(r"^submit", submit),
url(r"^add_comment", comment), re_path(r"^add_comment", comment),
url(r"^statistics", statistics_view), re_path(r"^statistics", statistics_view),
url(r"^export", export_view), re_path(r"^export", export_view),
url(r"^$", list_view), re_path(r"^$", list_view),
] ]
if settings.DEBUG: if settings.DEBUG:
+1 -1
View File
@@ -2,7 +2,7 @@
from django import forms from django import forms
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from members.models import Member, Payment, Request from members.models import Member, Payment, Request
+1 -1
View File
@@ -2,7 +2,7 @@
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db.models import Q, OuterRef, Subquery from django.db.models import Q, OuterRef, Subquery
+1 -1
View File
@@ -1,7 +1,7 @@
"""File containing member application django tables.""" """File containing member application django tables."""
import django_tables2 as tables import django_tables2 as tables
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db.models import F, OuterRef, Subquery from django.db.models import F, OuterRef, Subquery
from django.utils import timezone from django.utils import timezone
+33 -33
View File
@@ -1,6 +1,6 @@
"""File containing Member application URLs.""" """File containing Member application URLs."""
from django.conf.urls import url from django.urls import re_path
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
@@ -42,61 +42,61 @@ from members.views import application_submit
urlpatterns = [ urlpatterns = [
# landing page # landing page
url(r"^$", member_list), re_path(r"^$", member_list),
url(r"^list$", member_list), re_path(r"^list$", member_list),
# add member form view # add member form view
url(r"^add$", member_add), re_path(r"^add$", member_add),
# add many members view # add many members view
url(r"^add_many$", member_add_many), re_path(r"^add_many$", member_add_many),
# edit member information view # edit member information view
url(r"^edit/(?P<index>\d+)$", member_edit), re_path(r"^edit/(?P<index>\d+)$", member_edit),
# delete confirmation view # delete confirmation view
url(r"^delete_member_confirm/(?P<index>\d+)$", member_delete_confirm), re_path(r"^delete_member_confirm/(?P<index>\d+)$", member_delete_confirm),
# list all member applications # list all member applications
url(r"^applications$", application_list), re_path(r"^applications$", application_list),
# edit member application # edit member application
url(r"^edit_application/(?P<index>\d+)$", application_edit), re_path(r"^edit_application/(?P<index>\d+)$", application_edit),
# post request targets # post request targets
url(r"^submit_member$", member_submit), re_path(r"^submit_member$", member_submit),
url(r"^update_member$", member_update), re_path(r"^update_member$", member_update),
url(r"^delete_member$", member_delete), re_path(r"^delete_member$", member_delete),
url(r"^submit_payment$", payment_submit), re_path(r"^submit_payment$", payment_submit),
url(r"^update_payment$", payment_update), re_path(r"^update_payment$", payment_update),
url(r"^delete_payment$", payment_delete), re_path(r"^delete_payment$", payment_delete),
url(r"^submit_application$", application_submit), re_path(r"^submit_application$", application_submit),
url(r"^accept_application$", application_accept), re_path(r"^accept_application$", application_accept),
url(r"^delete_application$", application_delete), re_path(r"^delete_application$", application_delete),
# the actual member application form # the actual member application form
url(r"^application/$", application_form), re_path(r"^application/$", application_form),
# delete confirmation view for applications # delete confirmation view for applications
url(r"^delete_application_confirm/(?P<index>\d+)$", application_delete_confirm), re_path(r"^delete_application_confirm/(?P<index>\d+)$", application_delete_confirm),
# list all payment events # list all payment events
url(r"^payments$", payment_list), re_path(r"^payments$", payment_list),
# add payment event # add payment event
url(r"^add_payment$", payment_add), re_path(r"^add_payment$", payment_add),
# edit payment event # edit payment event
url(r"^edit_payment/(?P<index>\d+)$", payment_edit), re_path(r"^edit_payment/(?P<index>\d+)$", payment_edit),
# delete confirmation view # delete confirmation view
url(r"^delete_payment_confirm/(?P<index>\d+)$", payment_delete_confirm), re_path(r"^delete_payment_confirm/(?P<index>\d+)$", payment_delete_confirm),
# post endpoint for confirming multiple entries # post endpoint for confirming multiple entries
url(r"^add_many_confirm$", add_many_confirm), re_path(r"^add_many_confirm$", add_many_confirm),
# settings page # settings page
url(r"^settings$", settings_page), re_path(r"^settings$", settings_page),
# send CSV member data by POST # send CSV member data by POST
url(r"^import_csv", import_csv), re_path(r"^import_csv", import_csv),
# export members as excel file # export members as excel file
url(r"export_members", export_members_excel), re_path(r"export_members", export_members_excel),
url(r"export_payments", export_payments_excel), re_path(r"export_payments", export_payments_excel),
url(r"export_applications", export_applications_excel), re_path(r"export_applications", export_applications_excel),
# rest api url # rest api url
url(r"^api/members/(?P<pk>\d+)$", MemberDetail.as_view()), re_path(r"^api/members/(?P<pk>\d+)$", MemberDetail.as_view()),
# member select autocomplete view # member select autocomplete view
url( re_path(
r"^member-autocomplete/$", r"^member-autocomplete/$",
MemberAutoComplete.as_view(), MemberAutoComplete.as_view(),
name="member-autocomplete", name="member-autocomplete",
), ),
url(r"^check", CheckByEmail.as_view()), re_path(r"^check", CheckByEmail.as_view()),
] ]
if settings.DEBUG: if settings.DEBUG:
+1 -1
View File
@@ -1,4 +1,4 @@
"""File containing Members application views.""" """File containing Members application views."""
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
+1 -1
View File
@@ -4,7 +4,7 @@ from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from django.template.loader import render_to_string from django.template.loader import render_to_string
+2 -2
View File
@@ -10,7 +10,7 @@ from django.http import (
HttpResponseForbidden, HttpResponseForbidden,
) )
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from dal import autocomplete from dal import autocomplete
from django.utils import timezone from django.utils import timezone
@@ -249,7 +249,7 @@ class MemberAutoComplete(autocomplete.Select2QuerySetView):
if self.q: if self.q:
qs = Member.find_members_by_name(self.q) qs = Member.find_members_by_name(self.q)
return qs return qs.order_by("last_name")
class CheckByEmail(APIView): class CheckByEmail(APIView):
+1 -1
View File
@@ -4,7 +4,7 @@ from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
import logging import logging
+2 -2
View File
@@ -4,7 +4,7 @@ from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from django_tables2.config import RequestConfig from django_tables2.config import RequestConfig
@@ -135,7 +135,7 @@ def import_csv(request, *args, **kwargs):
member_table = MemberTable( member_table = MemberTable(
result.members, result.members,
request=request, request=request,
exclude=["id", "options"], exclude=["id", "options", "last_paid"],
attrs={"class": "table table-bordered table-hover"}, attrs={"class": "table table-bordered table-hover"},
) )
+1 -1
View File
@@ -1,7 +1,7 @@
"""File containing Ohlhafv forms.""" """File containing Ohlhafv forms."""
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from ohlhafv.models import OhlhafvChallenge from ohlhafv.models import OhlhafvChallenge
+1 -1
View File
@@ -5,7 +5,7 @@ from django.utils import timezone
from datetime import timedelta from datetime import timedelta
from django.contrib.auth.models import User from django.contrib.auth.models import User
from webapp.utils import month_from_now from webapp.utils import month_from_now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User from django.contrib.auth.models import User
from auditlog.registry import auditlog from auditlog.registry import auditlog
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
+1 -1
View File
@@ -1,6 +1,6 @@
import django_tables2 as tables import django_tables2 as tables
from django.db.models import Count, Q from django.db.models import Count, Q
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from ohlhafv.models import OhlhafvChallenge from ohlhafv.models import OhlhafvChallenge
+5 -5
View File
@@ -1,16 +1,16 @@
"""Ohlhafv urls.""" """Ohlhafv urls."""
from django.conf.urls import url from django.urls import re_path
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ohlhafv.views import * from ohlhafv.views import *
urlpatterns = [ urlpatterns = [
# ohlhafv # ohlhafv
url(r"^submit", ohlhafv_submit), re_path(r"^submit", ohlhafv_submit),
url(r"^list", ohlhafv_list), re_path(r"^list", ohlhafv_list),
url(r"^$", ohlhafv_view), re_path(r"^$", ohlhafv_view),
] ]
if settings.DEBUG: if settings.DEBUG:
+1 -1
View File
@@ -3,7 +3,7 @@ from django.shortcuts import render
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string from django.template.loader import render_to_string
from sikweb.settings import URL from sikweb.settings import URL
Generated
+928 -520
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -7,7 +7,7 @@ authors = ["Aarni Halinen aarni.halinen@sahkoinsinoorikilta.fi"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.9" python = "^3.9"
decorator = "^4.0.9" decorator = "^4.0.9"
Django = "^3.2.14" Django = "^4.1"
requests = "^2.28.1" requests = "^2.28.1"
django-cors-headers = "^3.13.0" django-cors-headers = "^3.13.0"
djangorestframework = "^3.12.4" djangorestframework = "^3.12.4"
@@ -19,8 +19,8 @@ django-auditlog = "^2.1.1"
django-phonenumber-field = {version = "^6.3.0", extras = ["phonenumbers"]} django-phonenumber-field = {version = "^6.3.0", extras = ["phonenumbers"]}
django-autocomplete-light = "^3.4.1" django-autocomplete-light = "^3.4.1"
six = "^1.12.0" six = "^1.12.0"
pyexcel = "^0.5.14" pyexcel = "^0.7.0"
pyexcel-xlsx = "^0.5.8" pyexcel-xlsx = "^0.6.0"
django-import-export = "^2.8.0" django-import-export = "^2.8.0"
openpyxl = "^2.6.4" openpyxl = "^2.6.4"
django-app-namespace-template-loader = "^0.4.1" django-app-namespace-template-loader = "^0.4.1"
@@ -38,6 +38,7 @@ python-dotenv = "^0.20.0"
djangorestframework-simplejwt = "^5.2.0" djangorestframework-simplejwt = "^5.2.0"
google-auth = "^2.9.1" google-auth = "^2.9.1"
google-api-python-client = "^2.54.0" google-api-python-client = "^2.54.0"
pyexcel-io = "^0.6.6"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
coverage = "^6.4.2" coverage = "^6.4.2"
+1 -1
View File
@@ -2,7 +2,7 @@ import os
import logging import logging
import datetime import datetime
from os.path import expanduser from os.path import expanduser
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+13 -28
View File
@@ -1,23 +1,6 @@
"""sikweb URL Configuration from django.urls import re_path, include
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Add an import: from blog import urls as blog_urls
2. Import the include() function: from django.conf.urls import url, include
3. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import url
from django.contrib import admin from django.contrib import admin
from django.views.static import serve as static_serve from django.views.static import serve as static_serve
from django.conf.urls import include
from django.conf.urls.static import static from django.conf.urls.static import static
from django.conf import settings from django.conf import settings
from django.contrib.staticfiles import views as static_views from django.contrib.staticfiles import views as static_views
@@ -27,18 +10,20 @@ favicon_view = RedirectView.as_view(url="static/img/favicon.png", permanent=True
urlpatterns = [ urlpatterns = [
url(r"", include("webapp.urls")), re_path(r"", include("webapp.urls")),
url(r"^members/", include("members.urls")), re_path(r"^members/", include("members.urls")),
url(r"^infoscreen/", include("infoscreen.urls")), re_path(r"^infoscreen/", include("infoscreen.urls")),
url(r"^kaehmy/", include("kaehmy.urls")), re_path(r"^kaehmy/", include("kaehmy.urls")),
url(r"^ohlhafv/", include("ohlhafv.urls")), re_path(r"^ohlhafv/", include("ohlhafv.urls")),
# favourite icon # favourite icon
url(r"^favicon\.ico$", favicon_view), re_path(r"^favicon\.ico$", favicon_view),
# admin # admin
url(r"^admin/", admin.site.urls), re_path(r"^admin/", admin.site.urls),
# i18n default view for changing the active language # i18n default view for changing the active language
url(r"^i18n/", include("django.conf.urls.i18n")), re_path(r"^i18n/", include("django.conf.urls.i18n")),
# staticfiles default view for static files in development # staticfiles default view for static files in development
url(r"^static/(?P<path>.*)$", static_views.serve), re_path(r"^static/(?P<path>.*)$", static_views.serve),
url(r"^media/(?P<path>.*)$", static_serve, {"document_root": settings.MEDIA_ROOT}), re_path(
r"^media/(?P<path>.*)$", static_serve, {"document_root": settings.MEDIA_ROOT}
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+1 -1
View File
@@ -10,7 +10,7 @@ from django.dispatch import receiver
import requests import requests
from uuid import uuid4 from uuid import uuid4
import logging import logging
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db.models import JSONField from django.db.models import JSONField
from auditlog.registry import auditlog from auditlog.registry import auditlog
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
+11 -6
View File
@@ -2,6 +2,7 @@ from django.contrib.auth.models import User, AnonymousUser
from django.utils import timezone from django.utils import timezone
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase, APIRequestFactory from rest_framework.test import APITestCase, APIRequestFactory
import zoneinfo
from webapp.models import Event from webapp.models import Event
from webapp.serializers import EventSerializer from webapp.serializers import EventSerializer
@@ -14,28 +15,30 @@ URL = "/api/events/"
class EventTestCase(APITestCase): class EventTestCase(APITestCase):
def setUp(self): def setUp(self):
tz = zoneinfo.ZoneInfo(key="Europe/Helsinki")
# Visible and relevant # Visible and relevant
test1 = createEventObject( test1 = createEventObject(
"Testitapahtuma1", start_time=timezone.datetime(2019, 11, 9, 12, 0, 0) "Testitapahtuma1",
start_time=timezone.datetime(2019, 11, 9, 12, 0, 0, tzinfo=tz),
) )
# Invisible but relevant # Invisible but relevant
createEventObject( createEventObject(
"Testitapahtuma2", "Testitapahtuma2",
visible=False, visible=False,
start_time=timezone.datetime(2018, 11, 9, 12, 0, 0), start_time=timezone.datetime(2018, 11, 9, 12, 0, 0, tzinfo=tz),
) )
# Visible but unrelevant # Visible but unrelevant
test2 = createEventObject( test2 = createEventObject(
"Testitapahtuma3", "Testitapahtuma3",
visible=True, visible=True,
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0), start_time=timezone.datetime(2018, 12, 9, 12, 0, 0, tzinfo=tz),
end_time=timezone.datetime(2018, 12, 9, 13, 0, 0), end_time=timezone.datetime(2018, 12, 9, 13, 0, 0, tzinfo=tz),
) )
# Visible and relevant # Visible and relevant
createEventObject( createEventObject(
"Testitapahtuma4", "Testitapahtuma4",
visible=True, visible=True,
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0), start_time=timezone.datetime(2018, 12, 9, 12, 0, 0, tzinfo=tz),
) )
# Add some tags # Add some tags
tag1 = tagBuilder() tag1 = tagBuilder()
@@ -77,7 +80,9 @@ class EventTestCase(APITestCase):
self.assertEqual(response.data["results"], expected) self.assertEqual(response.data["results"], expected)
def test_get_events_since(self): def test_get_events_since(self):
response = self.client.get(f"{URL}?since=2018-01-01", format="json") response = self.client.get(
f"{URL}?since=2018-01-01%2000:00:00%2B0200", format="json"
)
self.assertTrue(response.status_code, status.HTTP_200_OK) self.assertTrue(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data["results"]), 3) self.assertEqual(len(response.data["results"]), 3)
+3 -4
View File
@@ -1,7 +1,6 @@
"""Webapp urls.""" """Webapp urls."""
from django.conf.urls import url, include from django.urls import path, re_path, include
from django.urls import path
from rest_framework import routers from rest_framework import routers
from rest_framework_simplejwt.views import ( from rest_framework_simplejwt.views import (
TokenObtainPairView, TokenObtainPairView,
@@ -25,9 +24,9 @@ router.register(r"tags", TagsViewSet)
router.register(r"jobads", JobAdViewSet) router.register(r"jobads", JobAdViewSet)
urlpatterns = [ urlpatterns = [
url(r"^api/", include(router.urls)), re_path(r"^api/", include(router.urls)),
path(r"api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), path(r"api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path(r"api/token/verify/", TokenVerifyView.as_view(), name="token_verify"), path(r"api/token/verify/", TokenVerifyView.as_view(), name="token_verify"),
path(r"api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), path(r"api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
url(r"^jwt_nginx", nginx_jwt_resp), re_path(r"^jwt_nginx", nginx_jwt_resp),
] ]