@ -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)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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()`.
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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):
 | 
			
		||||
 | 
			
		||||
@ -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."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								notes.md
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user