diff --git a/aircox/admin/filters.py b/aircox/admin/filters.py index aab8e2f..f14f8e3 100644 --- a/aircox/admin/filters.py +++ b/aircox/admin/filters.py @@ -13,7 +13,7 @@ class DateFieldFilter(filters.FieldListFilter): input_type = "date" def __init__(self, field, request, params, model, model_admin, field_path): - self.field_generic = "%s__" % field_path + self.field_generic = f"{field_path}__" self.date_params = { k: v for k, v in params.items() if k.startswith(self.field_generic) } diff --git a/aircox/admin/mixins.py b/aircox/admin/mixins.py deleted file mode 100644 index f3a9cc2..0000000 --- a/aircox/admin/mixins.py +++ /dev/null @@ -1,41 +0,0 @@ -class UnrelatedInlineMixin: - """Inline class that can be included in an admin change view whose model is - not directly related to inline's model.""" - - view_model = None - parent_model = None - parent_fk = "" - - def __init__(self, parent_model, admin_site): - self.view_model = parent_model - super().__init__(self.parent_model, admin_site) - - def get_parent(self, view_obj): - """Get formset's instance from `obj` of AdminSite's change form.""" - field = self.parent_model._meta.get_field(self.parent_fk).remote_field - return getattr(view_obj, field.name, None) - - def save_parent(self, parent, view_obj): - """Save formset's instance.""" - setattr(parent, self.parent_fk, view_obj) - parent.save() - return parent - - def get_formset(self, request, obj): - ParentFormSet = super().get_formset(request, obj) - inline = self - - class FormSet(ParentFormSet): - view_obj = None - - def __init__(self, *args, instance=None, **kwargs): - self.view_obj = instance - instance = inline.get_parent(instance) - self.instance = instance - super().__init__(*args, instance=instance, **kwargs) - - def save(self): - inline.save_parent(self.instance, self.view_obj) - return super().save() - - return FormSet diff --git a/aircox/test.py b/aircox/test.py index 58635d9..36c6778 100644 --- a/aircox/test.py +++ b/aircox/test.py @@ -121,7 +121,7 @@ class SpoofMixin: if funcs is not None: self.funcs = funcs - def get_trace(self, name, args=False, kw=False): + def get_trace(self, name="__call__", args=False, kw=False): """Get a function call parameters. :param str name: function name @@ -137,7 +137,7 @@ class SpoofMixin: raise ValueError(f"{name} called multiple times.") return self._get_trace(trace, args=args, kw=kw) - def get_traces(self, name, args=False, kw=False): + def get_traces(self, name="__call__", args=False, kw=False): """Get a tuple of all call parameters. Parameters are the same as `get()`. diff --git a/aircox/tests/conftest.py b/aircox/tests/conftest.py index c99d469..173949a 100644 --- a/aircox/tests/conftest.py +++ b/aircox/tests/conftest.py @@ -3,6 +3,7 @@ import itertools import logging from django.contrib.auth.models import User +from django.test import RequestFactory import pytest from model_bakery import baker @@ -11,6 +12,10 @@ from aircox import models from aircox.test import Interface +req_factory = RequestFactory() +"""Request Factory used among different tests.""" + + @pytest.fixture def staff_user(): return baker.make(User, is_active=True, is_staff=True) @@ -25,8 +30,13 @@ def logger(): @pytest.fixture -def stations(): - return baker.make(models.Station, _quantity=2) +def station(): + return baker.make(models.Station, audio_streams="stream 1\nstream 2") + + +@pytest.fixture +def stations(station): + return [station, baker.make(models.Station)] @pytest.fixture @@ -35,7 +45,11 @@ def programs(stations): itertools.chain( *( baker.make( - models.Program, station=station, cover=None, _quantity=2 + models.Program, + station=station, + cover=None, + status=models.Program.STATUS_PUBLISHED, + _quantity=2, ) for station in stations ) diff --git a/aircox/tests/test_admin_site.py b/aircox/tests/test_admin_site.py index 7af82a0..62234c9 100644 --- a/aircox/tests/test_admin_site.py +++ b/aircox/tests/test_admin_site.py @@ -1,13 +1,14 @@ from django.urls import path, reverse -from django.test import RequestFactory from django.utils.translation import gettext_lazy as _ import pytest from aircox import admin_site, urls as _urls +from .conftest import req_factory -reqs = RequestFactory() +# Just for code quality: urls module is required because we need some +# url resolvers to be registered in order to run tests. _urls @@ -19,7 +20,7 @@ def site(): class TestAdminSite: @pytest.mark.django_db def test_each_context(self, site, staff_user): - req = reqs.get("admin/test") + req = req_factory.get("admin/test") req.user = staff_user context = site.each_context(req) assert "programs" in context diff --git a/aircox/views/base.py b/aircox/views/base.py index a41ccc1..a52afda 100644 --- a/aircox/views/base.py +++ b/aircox/views/base.py @@ -48,9 +48,7 @@ class BaseView(TemplateResponseMixin, ContextMixin): kwargs["sidebar_list_url"] = self.get_sidebar_url() if "audio_streams" not in kwargs: - streams = self.station.audio_streams - streams = streams and streams.split("\n") - kwargs["audio_streams"] = streams + kwargs["audio_streams"] = self.station.streams if "model" not in kwargs: model = ( @@ -63,7 +61,7 @@ class BaseView(TemplateResponseMixin, ContextMixin): return super().get_context_data(**kwargs) -# FIXME: rename to sth like [Base]?StationAPIView +# FIXME: rename to sth like [Base]?StationAPIView/Mixin class BaseAPIView: @property def station(self): diff --git a/aircox/views/mixins.py b/aircox/views/mixins.py index 3edf1bd..a4e98d1 100644 --- a/aircox/views/mixins.py +++ b/aircox/views/mixins.py @@ -91,6 +91,8 @@ class AttachedToMixin: return super().get_page() +# FIXME: django-filter provides filter mixin, but I don't remember why this is +# used. class FiltersMixin: """Mixin integrating Django filters' filter set.""" diff --git a/notes.md b/notes.md index a021f21..d9dcba9 100755 --- a/notes.md +++ b/notes.md @@ -76,6 +76,6 @@ cms: # For the next version: ## Refactorisation -Move: -- into `aircox_streamer`: `Log`, `Port` -- into `aircox_cms`: `Page`, `NavItem`, `Category`, `StaticPage`, etc. +- move into `aircox_streamer`: `Log`, `Port` +- move into `aircox_cms`: `Page`, `NavItem`, `Category`, `StaticPage`, etc. +- use TextChoice and IntegerChoices in models fields enums