notes
This commit is contained in:
parent
1aababe2ae
commit
722f76767e
|
@ -143,6 +143,9 @@ class Program(Page):
|
||||||
def save(self, *kargs, **kwargs):
|
def save(self, *kargs, **kwargs):
|
||||||
from .sound import Sound
|
from .sound import Sound
|
||||||
|
|
||||||
|
# FIXME: can be moved here to avoid multiple database hits
|
||||||
|
self.set_group_ownership()
|
||||||
|
|
||||||
super().save(*kargs, **kwargs)
|
super().save(*kargs, **kwargs)
|
||||||
|
|
||||||
# TODO: move in signals
|
# TODO: move in signals
|
||||||
|
@ -158,9 +161,6 @@ class Program(Page):
|
||||||
shutil.move(abspath, self.abspath)
|
shutil.move(abspath, self.abspath)
|
||||||
Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
|
Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
|
||||||
|
|
||||||
self.set_group_ownership()
|
|
||||||
super().save(*kargs, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ProgramChildQuerySet(PageQuerySet):
|
class ProgramChildQuerySet(PageQuerySet):
|
||||||
def station(self, station=None, id=None):
|
def station(self, station=None, id=None):
|
||||||
|
|
|
@ -59,8 +59,12 @@ def do_get_tracks(obj):
|
||||||
@register.simple_tag(name="has_perm", takes_context=True)
|
@register.simple_tag(name="has_perm", takes_context=True)
|
||||||
def do_has_perm(context, obj, perm, user=None, simple=False):
|
def do_has_perm(context, obj, perm, user=None, simple=False):
|
||||||
"""Return True if ``user.has_perm('[APP].[perm]_[MODEL]')``"""
|
"""Return True if ``user.has_perm('[APP].[perm]_[MODEL]')``"""
|
||||||
|
# FIXME: is there any case when this method is used without obj?
|
||||||
|
# => here we assume this shouldn't happen: obj has no default value,
|
||||||
|
# If it still required, you should return a boolean value in order
|
||||||
|
# to keep the same signature and contract with the function.
|
||||||
if not obj:
|
if not obj:
|
||||||
return
|
return False
|
||||||
if user is None:
|
if user is None:
|
||||||
user = context["request"].user
|
user = context["request"].user
|
||||||
if simple:
|
if simple:
|
||||||
|
@ -104,8 +108,9 @@ def do_player_live_attr(context):
|
||||||
@register.simple_tag(name="nav_items", takes_context=True)
|
@register.simple_tag(name="nav_items", takes_context=True)
|
||||||
def do_nav_items(context, menu, **kwargs):
|
def do_nav_items(context, menu, **kwargs):
|
||||||
"""Render navigation items for the provided menu name."""
|
"""Render navigation items for the provided menu name."""
|
||||||
if not getattr(context["request"], "station"):
|
# This should not happen
|
||||||
return []
|
# if not getattr(context["request"], "station"):
|
||||||
|
# return []
|
||||||
station, request = context["station"], context["request"]
|
station, request = context["station"], context["request"]
|
||||||
return [(item, item.render(request, **kwargs)) for item in station.navitem_set.filter(menu=menu)]
|
return [(item, item.render(request, **kwargs)) for item in station.navitem_set.filter(menu=menu)]
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from aircox.models import Program
|
from aircox.models import Program
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: better to be put in an external file, eventually load only once in tests.conftest
|
||||||
png_content = (
|
png_content = (
|
||||||
b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde"
|
b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde"
|
||||||
+ b"\x00\x00\x00\x0cIDATx\x9cc`\xf8\xcf\x00\x00\x02\x02\x01\x00{\t\x81x\x00\x00\x00\x00IEND\xaeB`\x82"
|
+ b"\x00\x00\x00\x0cIDATx\x9cc`\xf8\xcf\x00\x00\x02\x02\x01\x00{\t\x81x\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||||
|
@ -58,6 +59,8 @@ def test_edit_tracklist(user, client, program, episode, tracks):
|
||||||
tracklist = [t.id for t in episode.track_set.all().order_by("position")]
|
tracklist = [t.id for t in episode.track_set.all().order_by("position")]
|
||||||
tracklist_details_reversed = [(t.id, t.artist, t.title) for t in episode.track_set.all().order_by("-position")]
|
tracklist_details_reversed = [(t.id, t.artist, t.title) for t in episode.track_set.all().order_by("-position")]
|
||||||
tracklist_details_reversed = list(chain(*tracklist_details_reversed))
|
tracklist_details_reversed = list(chain(*tracklist_details_reversed))
|
||||||
|
# FIXME: for this too. If you wan't it cleaner
|
||||||
|
# also use `.format` instead of `%`.
|
||||||
data = """{"website": [""], "content": ["foobar"], "new_podcast": [""], "form-TOTAL_FORMS": ["3"],
|
data = """{"website": [""], "content": ["foobar"], "new_podcast": [""], "form-TOTAL_FORMS": ["3"],
|
||||||
"form-INITIAL_FORMS": ["3"], "form-MIN_NUM_FORMS": ["0"], "form-MAX_NUM_FORMS": ["1000"], "form-0-position": ["0"],
|
"form-INITIAL_FORMS": ["3"], "form-MIN_NUM_FORMS": ["0"], "form-MAX_NUM_FORMS": ["1000"], "form-0-position": ["0"],
|
||||||
"form-0-id": ["%s"], "form-0-": ["", "", "", "", "", ""], "form-0-artist": ["%s"], "form-0-title": ["%s"],
|
"form-0-id": ["%s"], "form-0-": ["", "", "", "", "", ""], "form-0-artist": ["%s"], "form-0-title": ["%s"],
|
||||||
|
@ -70,4 +73,9 @@ def test_edit_tracklist(user, client, program, episode, tracks):
|
||||||
)
|
)
|
||||||
r = client.post(reverse("episode-edit", kwargs={"pk": episode.pk}), json.loads(data), follow=True)
|
r = client.post(reverse("episode-edit", kwargs={"pk": episode.pk}), json.loads(data), follow=True)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert [t.id for t in episode.track_set.all().order_by("position")] == list(reversed(tracklist))
|
# FIXME: u can use set and values_list for comparison. It might be possible in this case that `all()` is not
|
||||||
|
# required.
|
||||||
|
# also you can create directly tracklist as a set: tracklist = set(episode.track_set.all().order_by("position"))
|
||||||
|
# => insertion order is preserved in python 3.*
|
||||||
|
assert set(episode.track_set.all().values_list("id", flat=True)) == set(tracklist)
|
||||||
|
# assert [t.id for t in episode.track_set.all().order_by("position")] == list(reversed(tracklist))
|
||||||
|
|
|
@ -53,6 +53,7 @@ class PodcastListView(EpisodeListView):
|
||||||
queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
|
queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: to move in aircox.forms
|
||||||
class EpisodeForm(ModelForm):
|
class EpisodeForm(ModelForm):
|
||||||
content = RichTextField()
|
content = RichTextField()
|
||||||
new_podcast = FileField(required=False)
|
new_podcast = FileField(required=False)
|
||||||
|
|
|
@ -16,6 +16,8 @@ __all__ = [
|
||||||
"BasePageDetailView",
|
"BasePageDetailView",
|
||||||
"PageDetailView",
|
"PageDetailView",
|
||||||
"PageListView",
|
"PageListView",
|
||||||
|
# FIXME: don't forget to export public members of the module ;)
|
||||||
|
"PageUpdateView",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,13 @@ from django.template.response import TemplateResponse
|
||||||
from aircox.models import Program
|
from aircox.models import Program
|
||||||
|
|
||||||
|
|
||||||
|
# Note: this is always better to use class-based view, even for a simple templated
|
||||||
|
# one. There is aircox.views.View class that provides the current station and other utils.
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def profile(request):
|
def profile(request):
|
||||||
programs = []
|
groups = request.user.groups.all()
|
||||||
ugroups = request.user.groups.all()
|
programs = Program.objects.filter(editors__in=groups)
|
||||||
for p in Program.objects.all():
|
|
||||||
if p.editors in ugroups:
|
|
||||||
programs.append(p)
|
|
||||||
context = {"user": request.user, "programs": programs}
|
context = {"user": request.user, "programs": programs}
|
||||||
return TemplateResponse(request, "accounts/profile.html", context)
|
return TemplateResponse(request, "accounts/profile.html", context)
|
||||||
|
|
|
@ -12,7 +12,7 @@ from ..models import Article, Episode, Page, Program, StaticPage
|
||||||
from .mixins import ParentMixin
|
from .mixins import ParentMixin
|
||||||
from .page import PageDetailView, PageListView, PageUpdateView
|
from .page import PageDetailView, PageListView, PageUpdateView
|
||||||
|
|
||||||
__all__ = ["ProgramPageDetailView", "ProgramDetailView", "ProgramPageListView"]
|
__all__ = ["ProgramPageDetailView", "ProgramDetailView", "ProgramPageListView", "ProgramUpdateView"]
|
||||||
|
|
||||||
|
|
||||||
class BaseProgramMixin:
|
class BaseProgramMixin:
|
||||||
|
@ -56,6 +56,7 @@ class ProgramDetailView(BaseProgramMixin, PageDetailView):
|
||||||
return super().get_template_names() + ["aircox/program_detail.html"]
|
return super().get_template_names() + ["aircox/program_detail.html"]
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: forms should be put in aircox.forms
|
||||||
class ProgramForm(ModelForm):
|
class ProgramForm(ModelForm):
|
||||||
content = RichTextField()
|
content = RichTextField()
|
||||||
new_cover = ImageField(required=False)
|
new_cover = ImageField(required=False)
|
||||||
|
@ -76,9 +77,7 @@ class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
|
||||||
model = Program
|
model = Program
|
||||||
form_class = ProgramForm
|
form_class = ProgramForm
|
||||||
|
|
||||||
def get_sidebar_queryset(self):
|
# FIXME: ???
|
||||||
return super().get_sidebar_queryset().filter(parent=self.program)
|
|
||||||
|
|
||||||
def test_func(self):
|
def test_func(self):
|
||||||
program = self.get_object()
|
program = self.get_object()
|
||||||
return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)
|
return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)
|
||||||
|
|
5
dev-1.0-121-notes.md
Normal file
5
dev-1.0-121-notes.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- nav_items: this method should be called only if there is a station in the context.
|
||||||
|
- idea behind the station is that a station is always defined, except in one case: just right the platform is installed. Otherwise the idea is that user can eventually select the station through a dropbox in the nav menu (happened in last versions of aircox in the admin, should still be there).
|
||||||
|
- don't forget to add your exported module member name to __all__ ;)
|
||||||
|
- it is better to put forms inside aircox.forms submodule (as aircox.forms.program subfiles, etc. if the file is to big + reexport in aircox.forms.__init__)
|
||||||
|
- you can eventually regroup urls under "/admin" or sth like this, in order to avoid mixing public and backoffice urls.
|
Loading…
Reference in New Issue
Block a user