update tracks, work on admin, fix stuff and models

This commit is contained in:
bkfox 2015-08-24 21:08:26 +02:00
parent b36c2f944e
commit 682d8b9189
5 changed files with 160 additions and 56 deletions

View File

@ -1,11 +1,11 @@
import copy import copy
from django.contrib import admin from django.contrib import admin
from django.forms import Textarea
from django.db import models from django.db import models
# import autocomplete_light as al from suit.admin import SortableTabularInline
from programs.forms import *
from programs.models import * from programs.models import *
@ -13,13 +13,6 @@ from programs.models import *
# Inlines # Inlines
# #
# TODO: inherits from the corresponding admin view # 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): class ScheduleInline (admin.TabularInline):
model = Schedule model = Schedule
extra = 1 extra = 1
@ -27,11 +20,20 @@ class ScheduleInline (admin.TabularInline):
class DiffusionInline (admin.TabularInline): class DiffusionInline (admin.TabularInline):
model = Diffusion model = Diffusion
raw_id_fields=('parent',) fields = ('episode', 'type', 'begin', 'end', 'stream')
fields = ('parent', 'type', 'date') readonly_fields = ('begin', 'end', 'stream')
extra = 1 extra = 1
class TrackInline (SortableTabularInline):
fields = ['artist', 'title', 'tags', 'position']
form = TrackForm
model = Track
sortable = 'position'
extra = 10
# #
# Parents # Parents
# #
@ -41,7 +43,7 @@ class MetadataAdmin (admin.ModelAdmin):
'fields': [ 'title', 'tags' ] 'fields': [ 'title', 'tags' ]
}), }),
( None, { ( None, {
'fields': [ 'date' ], 'fields': [ 'date', 'public', 'enumerable' ],
}), }),
] ]
@ -52,17 +54,19 @@ class MetadataAdmin (admin.ModelAdmin):
obj.save() obj.save()
from autocomplete_light.contrib.taggit_field import TaggitWidget, TaggitField
class PublicationAdmin (MetadataAdmin): class PublicationAdmin (MetadataAdmin):
fieldsets = copy.deepcopy(MetadataAdmin.fieldsets) fieldsets = copy.deepcopy(MetadataAdmin.fieldsets)
list_display = ('id', 'title', 'date', 'private') list_display = ('id', 'title', 'date', 'public', 'parent')
list_filter = ['date', 'private'] list_filter = ['date', 'public', 'parent', 'author']
search_fields = ['title', 'content'] search_fields = ['title', 'content']
fieldsets[0][1]['fields'].insert(1, 'subtitle') fieldsets[0][1]['fields'].insert(1, 'subtitle')
fieldsets[0][1]['fields'] += [ 'img', 'content' ] 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): class EpisodeAdmin (PublicationAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
#inlines = [ SoundInline ]
list_filter = ['parent'] + PublicationAdmin.list_filter list_filter = ['parent'] + PublicationAdmin.list_filter
# FIXME later: when we have thousands of tracks
fieldsets[0][1]['fields'] += ['tracks']
fieldsets[0][1]['fields'] += ['sounds'] fieldsets[0][1]['fields'] += ['sounds']
raw_id_fields = ('tracks', 'sounds') inlines = (TrackInline, DiffusionInline)
autocomplete_lookup_fields = {
'm2m': ['tracks', 'sounds'],
} 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(Track)
admin.site.register(Sound, SoundAdmin) admin.site.register(Sound, SoundAdmin)
@ -108,5 +114,5 @@ admin.site.register(Schedule)
admin.site.register(Article, ArticleAdmin) admin.site.register(Article, ArticleAdmin)
admin.site.register(Program, ProgramAdmin) admin.site.register(Program, ProgramAdmin)
admin.site.register(Episode, EpisodeAdmin) admin.site.register(Episode, EpisodeAdmin)
admin.site.register(Diffusion) admin.site.register(Diffusion, DiffusionAdmin)

View File

@ -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'''
<span class="block" data-value="%s">%s</span>
'''
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)

19
programs/forms.py Normal file
View File

@ -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'),
}

View File

@ -50,9 +50,9 @@ ugettext_lazy('one on two')
DiffusionType = { DiffusionType = {
'diffuse': 0x01 # the diffusion is planified or done '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 , 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give
# the info to the users # the info to the users
, 'stop': 0x04 # the diffusion been arbitrary stopped (non-stop or not)
} }
@ -107,10 +107,15 @@ class Metadata (Model):
_('date') _('date')
, default = timezone.datetime.now , default = timezone.datetime.now
) )
private = models.BooleanField( public = models.BooleanField(
_('private') _('public')
, default = False , default = True
, help_text = _('publication is private') , help_text = _('publication is public')
)
enumerable = models.BooleanField(
_('enumerable')
, default = True
, help_text = _('publication is listable')
) )
tags = TaggableManager( tags = TaggableManager(
_('tags') _('tags')
@ -143,7 +148,7 @@ class Publication (Metadata):
_('content') _('content')
, blank = True , blank = True
) )
can_comment = models.BooleanField( commentable = models.BooleanField(
_('enable comments') _('enable comments')
, default = True , default = True
, help_text = _('comments are enabled on this publication') , help_text = _('comments are enabled on this publication')
@ -209,32 +214,31 @@ class Publication (Metadata):
# Usable models # Usable models
# #
class Track (Model): 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 = models.CharField(
_('artist') _('artist')
, max_length = 128 , max_length = 128
, blank = True
) )
title = models.CharField( title = models.CharField(
_('title') _('title')
, max_length = 128 , max_length = 128
) )
version = models.CharField(
_('version')
, max_length = 128
, blank = True
, help_text = _('additional informations on that track')
)
tags = TaggableManager( blank = True ) tags = TaggableManager( blank = True )
# position can be used to specify a position in seconds
position = models.SmallIntegerField(
@staticmethod default = 0
def autocomplete_search_fields(): , help_text=_('position in the playlist')
return ("artist__icontains", 'title__icontains') )
def __str__(self): def __str__(self):
return ' '.join([self.artist, ':', self.title, return ' '.join([self.artist, ':', self.title])
(self.version and ('(' + self.version + ')') or '') ])
class Meta: class Meta:
@ -532,12 +536,14 @@ class Program (Publication):
, null = True , null = True
, help_text = _('parent article') , help_text = _('parent article')
) )
email = models.EmailField( email = models.EmailField(
_('email') _('email')
, max_length = 128 , max_length = 128
, null = True , null = True
, blank = True , blank = True
) )
url = models.URLField( url = models.URLField(
_('website') _('website')
, blank = True , blank = True
@ -567,6 +573,7 @@ class Program (Publication):
verbose_name_plural = _('Programs') verbose_name_plural = _('Programs')
class Episode (Publication): class Episode (Publication):
# Note: # Note:
# We do not especially need a duration here, because even if an # We do not especially need a duration here, because even if an
@ -581,11 +588,6 @@ class Episode (Publication):
, verbose_name = _('parent') , verbose_name = _('parent')
, help_text = _('parent program') , help_text = _('parent program')
) )
tracks = models.ManyToManyField(
Track
, blank = True
, verbose_name = _('tracks')
)
sounds = models.ManyToManyField( sounds = models.ManyToManyField(
Sound Sound
, blank = True , blank = True
@ -620,23 +622,24 @@ class Diffusion (Model):
verbose_name = _('type') verbose_name = _('type')
, choices = [ (y, x) for x,y in DiffusionType.items() ] , 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( stream = models.SmallIntegerField(
verbose_name = _('stream') verbose_name = _('stream')
, default = 0 , default = 0
, help_text = 'stream id on which the diffusion happens' , 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): def save (self, *args, **kwargs):
if self.episode: if self.episode:
self.program = self.episode.parent self.program = self.episode.parent
super(Diffusion, self).save(*args, **kwargs) super(Diffusion, self).save(*args, **kwargs)
def __str__ (self):
return self.program.title + ' on ' + str(self.start) \
+ str(self.type)
class Meta: class Meta:
verbose_name = _('Diffusion') verbose_name = _('Diffusion')

View File

@ -1,8 +1,33 @@
{% extends "admin/base.html" %} {% extends "admin/base.html" %}
{% block extrahead %} {% block extrahead %}
{% include 'autocomplete_light/static.html' %}
<style> <style>
/** autocomplete override **/
.autocomplete-light-widget .deck [data-value] .remove {
float: right;
}
.autocomplete-light-widget .deck [data-value],
.autocomplete-light-widget .deck .choice {
display: block;
}
.control-group .add-related,
.inline-group .add-related {
vertical-align: bottom;
}
/** suit **/
.controls textarea,
.controls .vTextField {
width: calc(100% - 10px);
}
/** grappelli **/
.grp-autocomplete-wrapper-m2m:focus, .grp-autocomplete-wrapper-m2m.grp-state-focus, .grp-autocomplete-wrapper-m2m:focus, .grp-autocomplete-wrapper-m2m.grp-state-focus,
.grp-autocomplete-wrapper-m2m { .grp-autocomplete-wrapper-m2m {
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.2);
@ -19,6 +44,7 @@
float: none; float: none;
display: block; display: block;
} }
</style> </style>
{% endblock %} {% endblock %}