diff --git a/programs/admin.py b/programs/admin.py
index 955c8ec..9e239be 100755
--- a/programs/admin.py
+++ b/programs/admin.py
@@ -1,11 +1,11 @@
import copy
from django.contrib import admin
-from django.forms import Textarea
from django.db import models
-# import autocomplete_light as al
+from suit.admin import SortableTabularInline
+from programs.forms import *
from programs.models import *
@@ -13,13 +13,6 @@ from programs.models import *
# Inlines
#
# TODO: inherits from the corresponding admin view
-class SoundInline (admin.TabularInline):
- model = Sound
- raw_id_fields=('parent',)
- fields = ('title', 'private', 'tags', 'file', 'duration', 'fragment')
- extra = 1
-
-
class ScheduleInline (admin.TabularInline):
model = Schedule
extra = 1
@@ -27,11 +20,20 @@ class ScheduleInline (admin.TabularInline):
class DiffusionInline (admin.TabularInline):
model = Diffusion
- raw_id_fields=('parent',)
- fields = ('parent', 'type', 'date')
+ fields = ('episode', 'type', 'begin', 'end', 'stream')
+ readonly_fields = ('begin', 'end', 'stream')
extra = 1
+
+class TrackInline (SortableTabularInline):
+ fields = ['artist', 'title', 'tags', 'position']
+ form = TrackForm
+ model = Track
+ sortable = 'position'
+ extra = 10
+
+
#
# Parents
#
@@ -41,7 +43,7 @@ class MetadataAdmin (admin.ModelAdmin):
'fields': [ 'title', 'tags' ]
}),
( None, {
- 'fields': [ 'date' ],
+ 'fields': [ 'date', 'public', 'enumerable' ],
}),
]
@@ -52,17 +54,19 @@ class MetadataAdmin (admin.ModelAdmin):
obj.save()
+from autocomplete_light.contrib.taggit_field import TaggitWidget, TaggitField
class PublicationAdmin (MetadataAdmin):
fieldsets = copy.deepcopy(MetadataAdmin.fieldsets)
- list_display = ('id', 'title', 'date', 'private')
- list_filter = ['date', 'private']
+ list_display = ('id', 'title', 'date', 'public', 'parent')
+ list_filter = ['date', 'public', 'parent', 'author']
search_fields = ['title', 'content']
fieldsets[0][1]['fields'].insert(1, 'subtitle')
fieldsets[0][1]['fields'] += [ 'img', 'content' ]
- fieldsets[1][1]['fields'] += [ 'parent', 'private', 'can_comment' ] #, 'meta' ],
+ fieldsets[1][1]['fields'] += [ 'parent' ] #, 'meta' ],
+
#
@@ -90,17 +94,19 @@ class ProgramAdmin (PublicationAdmin):
class EpisodeAdmin (PublicationAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
- #inlines = [ SoundInline ]
list_filter = ['parent'] + PublicationAdmin.list_filter
- # FIXME later: when we have thousands of tracks
- fieldsets[0][1]['fields'] += ['tracks']
fieldsets[0][1]['fields'] += ['sounds']
- raw_id_fields = ('tracks', 'sounds')
- autocomplete_lookup_fields = {
- 'm2m': ['tracks', 'sounds'],
- }
+ inlines = (TrackInline, DiffusionInline)
+
+
+class DiffusionAdmin (admin.ModelAdmin):
+ list_display = ('type', 'begin', 'end', 'episode', 'program', 'stream')
+ list_filter = ('type', 'begin', 'program', 'stream')
+
+
+
admin.site.register(Track)
admin.site.register(Sound, SoundAdmin)
@@ -108,5 +114,5 @@ admin.site.register(Schedule)
admin.site.register(Article, ArticleAdmin)
admin.site.register(Program, ProgramAdmin)
admin.site.register(Episode, EpisodeAdmin)
-admin.site.register(Diffusion)
+admin.site.register(Diffusion, DiffusionAdmin)
diff --git a/programs/autocomplete_light_registry.py b/programs/autocomplete_light_registry.py
new file mode 100644
index 0000000..fd75aac
--- /dev/null
+++ b/programs/autocomplete_light_registry.py
@@ -0,0 +1,50 @@
+import autocomplete_light.shortcuts as al
+from programs.models import *
+
+from taggit.models import Tag
+al.register(Tag)
+
+
+class OneFieldAutocomplete(al.AutocompleteModelBase):
+ choice_html_format = u'''
+ %s
+ '''
+
+ def choice_html (self, choice):
+ value = choice[self.search_fields[0]]
+ return self.choice_html_format % (self.choice_label(choice),
+ self.choice_label(value))
+
+
+ def choices_for_request(self):
+ #if not self.request.user.is_staff:
+ # self.choices = self.choices.filter(private=False)
+ filter_args = { self.search_fields[0] + '__icontains': self.request.GET['q'] }
+
+ self.choices = self.choices.filter(**filter_args)
+ self.choices = self.choices.values(self.search_fields[0]).distinct()
+ return self.choices
+
+
+class TrackArtistAutocomplete(OneFieldAutocomplete):
+ search_fields = ['artist']
+ model = Track
+
+al.register(TrackArtistAutocomplete)
+
+
+class TrackTitleAutocomplete(OneFieldAutocomplete):
+ search_fields = ['title']
+ model = Track
+
+
+al.register(TrackTitleAutocomplete)
+
+
+#class DiffusionAutocomplete(OneFieldAutocomplete):
+# search_fields = ['episode', 'program', 'start', 'stop']
+# model = Diffusion
+#
+#al.register(DiffusionAutocomplete)
+
+
diff --git a/programs/forms.py b/programs/forms.py
new file mode 100644
index 0000000..828d541
--- /dev/null
+++ b/programs/forms.py
@@ -0,0 +1,19 @@
+from django import forms
+from django.contrib.admin import widgets
+
+import autocomplete_light.shortcuts as al
+from autocomplete_light.contrib.taggit_field import TaggitWidget
+
+from programs.models import *
+
+
+class TrackForm (forms.ModelForm):
+ class Meta:
+ model = Track
+ fields = ['artist', 'title', 'tags', 'position']
+ widgets = {
+ 'artist': al.TextWidget('TrackArtistAutocomplete'),
+ 'title': al.TextWidget('TrackTitleAutocomplete'),
+ 'tags': TaggitWidget('TagAutocomplete'),
+ }
+
diff --git a/programs/models.py b/programs/models.py
index d2f402d..4e9dedd 100755
--- a/programs/models.py
+++ b/programs/models.py
@@ -49,10 +49,10 @@ ugettext_lazy('one on two')
DiffusionType = {
- 'diffuse': 0x01 # the diffusion is planified or done
- , 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give
+ 'diffuse': 0x01 # the diffusion is planified or done
+ , 'scheduled': 0x02 # the diffusion been scheduled automatically
+ , 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give
# the info to the users
- , 'stop': 0x04 # the diffusion been arbitrary stopped (non-stop or not)
}
@@ -107,10 +107,15 @@ class Metadata (Model):
_('date')
, default = timezone.datetime.now
)
- private = models.BooleanField(
- _('private')
- , default = False
- , help_text = _('publication is private')
+ public = models.BooleanField(
+ _('public')
+ , default = True
+ , help_text = _('publication is public')
+ )
+ enumerable = models.BooleanField(
+ _('enumerable')
+ , default = True
+ , help_text = _('publication is listable')
)
tags = TaggableManager(
_('tags')
@@ -143,7 +148,7 @@ class Publication (Metadata):
_('content')
, blank = True
)
- can_comment = models.BooleanField(
+ commentable = models.BooleanField(
_('enable comments')
, default = True
, help_text = _('comments are enabled on this publication')
@@ -209,32 +214,31 @@ class Publication (Metadata):
# Usable models
#
class Track (Model):
+ # There are no nice solution for M2M relations ship (even without
+ # through) in django-admin. So we unfortunately need to make one-
+ # to-one relations and add a position argument
+ episode = models.ForeignKey(
+ 'Episode'
+ , null = True
+ )
artist = models.CharField(
_('artist')
, max_length = 128
- , blank = True
)
title = models.CharField(
_('title')
, max_length = 128
)
- version = models.CharField(
- _('version')
- , max_length = 128
- , blank = True
- , help_text = _('additional informations on that track')
- )
tags = TaggableManager( blank = True )
-
-
- @staticmethod
- def autocomplete_search_fields():
- return ("artist__icontains", 'title__icontains')
+ # position can be used to specify a position in seconds
+ position = models.SmallIntegerField(
+ default = 0
+ , help_text=_('position in the playlist')
+ )
def __str__(self):
- return ' '.join([self.artist, ':', self.title,
- (self.version and ('(' + self.version + ')') or '') ])
+ return ' '.join([self.artist, ':', self.title])
class Meta:
@@ -532,12 +536,14 @@ class Program (Publication):
, null = True
, help_text = _('parent article')
)
+
email = models.EmailField(
_('email')
, max_length = 128
, null = True
, blank = True
)
+
url = models.URLField(
_('website')
, blank = True
@@ -567,6 +573,7 @@ class Program (Publication):
verbose_name_plural = _('Programs')
+
class Episode (Publication):
# Note:
# We do not especially need a duration here, because even if an
@@ -581,11 +588,6 @@ class Episode (Publication):
, verbose_name = _('parent')
, help_text = _('parent program')
)
- tracks = models.ManyToManyField(
- Track
- , blank = True
- , verbose_name = _('tracks')
- )
sounds = models.ManyToManyField(
Sound
, blank = True
@@ -620,23 +622,24 @@ class Diffusion (Model):
verbose_name = _('type')
, choices = [ (y, x) for x,y in DiffusionType.items() ]
)
- date = models.DateTimeField( _('date of diffusion start') )
+ begin = models.DateTimeField( _('start of diffusion start') )
+ end = models.DateTimeField( _('stop of diffusion stop') )
stream = models.SmallIntegerField(
verbose_name = _('stream')
, default = 0
, help_text = 'stream id on which the diffusion happens'
)
- scheduled = models.BooleanField(
- verbose_name = _('scheduled')
- , default = False
- , help_text = 'diffusion generated automatically'
- )
+
def save (self, *args, **kwargs):
if self.episode:
self.program = self.episode.parent
super(Diffusion, self).save(*args, **kwargs)
+ def __str__ (self):
+ return self.program.title + ' on ' + str(self.start) \
+ + str(self.type)
+
class Meta:
verbose_name = _('Diffusion')
diff --git a/templates/admin/base_site.html b/templates/admin/base_site.html
index a040f36..1e8b0e8 100644
--- a/templates/admin/base_site.html
+++ b/templates/admin/base_site.html
@@ -1,8 +1,33 @@
{% extends "admin/base.html" %}
{% block extrahead %}
+{% include 'autocomplete_light/static.html' %}
{% endblock %}