work on admin
This commit is contained in:
		@ -3,6 +3,9 @@ import copy
 | 
				
			|||||||
from django.contrib     import admin
 | 
					from django.contrib     import admin
 | 
				
			||||||
from django.forms       import Textarea
 | 
					from django.forms       import Textarea
 | 
				
			||||||
from django.db          import models
 | 
					from django.db          import models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import autocomplete_light as al
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from programs.models    import *
 | 
					from programs.models    import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,6 +54,13 @@ class MetadataAdmin (admin.ModelAdmin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PublicationAdmin (MetadataAdmin):
 | 
					class PublicationAdmin (MetadataAdmin):
 | 
				
			||||||
 | 
					    form = al.modelform_factory(
 | 
				
			||||||
 | 
					               Episode
 | 
				
			||||||
 | 
					             , fields = '__all__'
 | 
				
			||||||
 | 
					             # , autocomplete_fields = ['tracks']
 | 
				
			||||||
 | 
					             )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    formfield_overrides = {
 | 
					    formfield_overrides = {
 | 
				
			||||||
        models.TextField: {'widget': Textarea(attrs={'style':'width:calc(100% - 12px);'})},
 | 
					        models.TextField: {'widget': Textarea(attrs={'style':'width:calc(100% - 12px);'})},
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -72,8 +82,8 @@ class PublicationAdmin (MetadataAdmin):
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
class SoundFileAdmin (MetadataAdmin):
 | 
					class SoundFileAdmin (MetadataAdmin):
 | 
				
			||||||
    fieldsets = [
 | 
					    fieldsets = [
 | 
				
			||||||
        (None, { 'fields': ['title', 'tags', 'file', 'embed' ] } ),
 | 
					        (None, { 'fields': ['title', 'tags', 'file' ] } ),
 | 
				
			||||||
        ('metadata', { 'fields': ['duration', 'date', 'podcastable', 'fragment' ] } )
 | 
					        (None, { 'fields': ['duration', 'date', 'fragment' ] } )
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -90,13 +100,16 @@ class ProgramAdmin (PublicationAdmin):
 | 
				
			|||||||
    fieldsets[1][1]['fields'] += ['email', 'url']
 | 
					    fieldsets[1][1]['fields'] += ['email', 'url']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EpisodeAdmin (PublicationAdmin):
 | 
					class EpisodeAdmin (PublicationAdmin):
 | 
				
			||||||
    fieldsets           = copy.deepcopy(PublicationAdmin.fieldsets)
 | 
					    fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
 | 
				
			||||||
    inlines             = [ SoundFileInline ]
 | 
					    #inlines             = [ SoundFileInline ]
 | 
				
			||||||
    list_filter         = ['parent'] + PublicationAdmin.list_filter
 | 
					    list_filter         = ['parent'] + PublicationAdmin.list_filter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # FIXME later: when we have thousands of tracks
 | 
					    # FIXME later: when we have thousands of tracks
 | 
				
			||||||
    fieldsets[0][1]['fields'] += ['tracks']
 | 
					    fieldsets[0][1]['fields'] += ['tracks']
 | 
				
			||||||
 | 
					    fieldsets[0][1]['fields'] += ['sounds']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								programs/autocomplete_light_registry.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								programs/autocomplete_light_registry.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					import autocomplete_light.shortcuts as al
 | 
				
			||||||
 | 
					from programs.models import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SoundAutocomplete(al.AutocompleteModelBase):
 | 
				
			||||||
 | 
					    search_fields = ['title', 'file']
 | 
				
			||||||
 | 
					    model = SoundFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					al.register(SoundAutocomplete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrackAutocomplete(al.AutocompleteModelBase):
 | 
				
			||||||
 | 
					    search_fields = ['artist', 'title']
 | 
				
			||||||
 | 
					    model = Track
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					al.register(TrackAutocomplete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ArticleAutocomplete(al.AutocompleteModelBase):
 | 
				
			||||||
 | 
					    search_fields = ['title', 'subtitle']
 | 
				
			||||||
 | 
					    model = Article
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					al.register(ArticleAutocomplete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProgramAutocomplete(al.AutocompleteModelBase):
 | 
				
			||||||
 | 
					    search_fields = ['title', 'subtitle']
 | 
				
			||||||
 | 
					    model = Program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					al.register(ProgramAutocomplete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EpisodeAutocomplete(al.AutocompleteModelBase):
 | 
				
			||||||
 | 
					    search_fields = ['title', 'subtitle']
 | 
				
			||||||
 | 
					    model = Episode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					al.register(EpisodeAutocomplete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -259,15 +259,11 @@ class SoundFile (Metadata):
 | 
				
			|||||||
        return os.path.join(path, filename)
 | 
					        return os.path.join(path, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parent      = models.ForeignKey(
 | 
					 | 
				
			||||||
                      'Episode'
 | 
					 | 
				
			||||||
                    , verbose_name = _('episode')
 | 
					 | 
				
			||||||
                    , blank = True
 | 
					 | 
				
			||||||
                    , null = True
 | 
					 | 
				
			||||||
                  )
 | 
					 | 
				
			||||||
    file        = models.FileField( #FIXME: filefield
 | 
					    file        = models.FileField( #FIXME: filefield
 | 
				
			||||||
                      _('file')
 | 
					                      _('file')
 | 
				
			||||||
                    , upload_to = get_upload_path
 | 
					                    , upload_to = get_upload_path
 | 
				
			||||||
 | 
					                    , blank = True
 | 
				
			||||||
 | 
					                    , null = True
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    duration    = models.TimeField(
 | 
					    duration    = models.TimeField(
 | 
				
			||||||
                      _('duration')
 | 
					                      _('duration')
 | 
				
			||||||
@ -430,6 +426,56 @@ class Schedule (Model):
 | 
				
			|||||||
        return dates
 | 
					        return dates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def diffusions_of_month (self, date = None, exclude_saved = False):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return a list of generated (unsaved) diffusions for this program for the
 | 
				
			||||||
 | 
					        month of the given date. If exclude_saved, exclude all diffusions that
 | 
				
			||||||
 | 
					        are yet in the database.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        When a diffusion is created, it tries to attach the corresponding
 | 
				
			||||||
 | 
					        episode.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if not date:
 | 
				
			||||||
 | 
					            date = timezone.datetime.today()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        diffusions = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dates = self.dates_of_month()
 | 
				
			||||||
 | 
					        saved = Diffusion.objects.filter( date__in = dates
 | 
				
			||||||
 | 
					                                        , program = self.parent )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # existing diffusions
 | 
				
			||||||
 | 
					        for saved_item in saved:
 | 
				
			||||||
 | 
					            dates.remove(saved_item.date)
 | 
				
			||||||
 | 
					            if not exclude_saved:
 | 
				
			||||||
 | 
					                diffusions.append(saved_item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # others
 | 
				
			||||||
 | 
					        for date in dates:
 | 
				
			||||||
 | 
					            # get episode
 | 
				
			||||||
 | 
					            ep_date = date
 | 
				
			||||||
 | 
					            if self.rerun:
 | 
				
			||||||
 | 
					                ep_date = self.rerun.date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            episode = Episode.objects().filter( date = ep_date
 | 
				
			||||||
 | 
					                                              , parent = self.parent )
 | 
				
			||||||
 | 
					            episode  = episode[0] if episode.count() else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # make diffusion
 | 
				
			||||||
 | 
					            diffusion = Diffusion( parent = episode
 | 
				
			||||||
 | 
					                         , program = self.parent
 | 
				
			||||||
 | 
					                         , type = DiffusionType['diffuse']
 | 
				
			||||||
 | 
					                         , date = date
 | 
				
			||||||
 | 
					                         , stream = settings.AIRCOX_SCHEDULED_STREAM
 | 
				
			||||||
 | 
					                         , selfd = True
 | 
				
			||||||
 | 
					                         )
 | 
				
			||||||
 | 
					            diffusion.program = self.program
 | 
				
			||||||
 | 
					            diffusions.append(diffusion)
 | 
				
			||||||
 | 
					        return diffusions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__ (self):
 | 
					    def __str__ (self):
 | 
				
			||||||
        frequency = [ x for x,y in Frequency.items() if y == self.frequency ]
 | 
					        frequency = [ x for x,y in Frequency.items() if y == self.frequency ]
 | 
				
			||||||
        return self.parent.title + ': ' + frequency[0]
 | 
					        return self.parent.title + ': ' + frequency[0]
 | 
				
			||||||
@ -447,6 +493,7 @@ class Article (Publication):
 | 
				
			|||||||
                  , verbose_name = _('parent')
 | 
					                  , verbose_name = _('parent')
 | 
				
			||||||
                  , blank = True
 | 
					                  , blank = True
 | 
				
			||||||
                  , null = True
 | 
					                  , null = True
 | 
				
			||||||
 | 
					                  , help_text = _('parent article')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    static_page = models.BooleanField(
 | 
					    static_page = models.BooleanField(
 | 
				
			||||||
                    _('static page')
 | 
					                    _('static page')
 | 
				
			||||||
@ -471,6 +518,7 @@ class Program (Publication):
 | 
				
			|||||||
                  , verbose_name = _('parent')
 | 
					                  , verbose_name = _('parent')
 | 
				
			||||||
                  , blank = True
 | 
					                  , blank = True
 | 
				
			||||||
                  , null = True
 | 
					                  , null = True
 | 
				
			||||||
 | 
					                  , help_text = _('parent article')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    email       = models.EmailField(
 | 
					    email       = models.EmailField(
 | 
				
			||||||
                    _('email')
 | 
					                    _('email')
 | 
				
			||||||
@ -491,16 +539,14 @@ class Program (Publication):
 | 
				
			|||||||
                           )
 | 
					                           )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_schedules (self, date):
 | 
					    def find_schedule (self, date):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return schedules that match a given date
 | 
					        Return the first schedule that matches a given date
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        schedules = Schedule.objects.filter(parent = self)
 | 
					        schedules = Schedule.objects.filter(parent = self)
 | 
				
			||||||
        r = []
 | 
					 | 
				
			||||||
        for schedule in schedules:
 | 
					        for schedule in schedules:
 | 
				
			||||||
            if schedule.match_date(date):
 | 
					            if schedule.match(date):
 | 
				
			||||||
                r.append(schedule)
 | 
					                return schedule
 | 
				
			||||||
        return r
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
@ -521,12 +567,17 @@ class Episode (Publication):
 | 
				
			|||||||
    parent      = models.ForeignKey(
 | 
					    parent      = models.ForeignKey(
 | 
				
			||||||
                      Program
 | 
					                      Program
 | 
				
			||||||
                    , verbose_name = _('parent')
 | 
					                    , verbose_name = _('parent')
 | 
				
			||||||
 | 
					                    , help_text = _('parent program')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    tracks      = SortedManyToManyField(
 | 
					    tracks      = SortedManyToManyField(
 | 
				
			||||||
 | 
					    #tracks      = models.ManyToManyField(
 | 
				
			||||||
                      Track
 | 
					                      Track
 | 
				
			||||||
                    , verbose_name = _('tracks')
 | 
					                    , verbose_name = _('tracks')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
 | 
					    sounds      = SortedManyToManyField(
 | 
				
			||||||
 | 
					                      SoundFile
 | 
				
			||||||
 | 
					                    , verbose_name = _('sounds')
 | 
				
			||||||
 | 
					                  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _('Episode')
 | 
					        verbose_name = _('Episode')
 | 
				
			||||||
@ -546,9 +597,11 @@ class Diffusion (Model):
 | 
				
			|||||||
                      Episode
 | 
					                      Episode
 | 
				
			||||||
                    , blank = True
 | 
					                    , blank = True
 | 
				
			||||||
                    , null = True
 | 
					                    , null = True
 | 
				
			||||||
 | 
					                    , verbose_name = _('episode')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    program     = models.ForeignKey (
 | 
					    program     = models.ForeignKey (
 | 
				
			||||||
                      Program
 | 
					                      Program
 | 
				
			||||||
 | 
					                    , verbose_name = _('program')
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    type        = models.SmallIntegerField(
 | 
					    type        = models.SmallIntegerField(
 | 
				
			||||||
                      verbose_name = _('type')
 | 
					                      verbose_name = _('type')
 | 
				
			||||||
@ -561,7 +614,7 @@ class Diffusion (Model):
 | 
				
			|||||||
                    , help_text = 'stream id on which the diffusion happens'
 | 
					                    , help_text = 'stream id on which the diffusion happens'
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
    scheduled   = models.BooleanField(
 | 
					    scheduled   = models.BooleanField(
 | 
				
			||||||
                      verbose_name = _('automated')
 | 
					                      verbose_name = _('scheduled')
 | 
				
			||||||
                    , default = False
 | 
					                    , default = False
 | 
				
			||||||
                    , help_text = 'diffusion generated automatically'
 | 
					                    , help_text = 'diffusion generated automatically'
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,52 +0,0 @@
 | 
				
			|||||||
from django.utils                   import timezone
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from programs.models                import Schedule, Diffusion, Episode,\
 | 
					 | 
				
			||||||
                                           DiffusionType
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def scheduled_month_diffusions (date = None, unsaved_only = False):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Return a list of scheduled diffusions for the month of the given date. For the
 | 
					 | 
				
			||||||
    non existing diffusions, a program attribute to the corresponding program is
 | 
					 | 
				
			||||||
    set.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    if not date:
 | 
					 | 
				
			||||||
        date = timezone.datetime.today()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    schedules = Schedule.objects.all()
 | 
					 | 
				
			||||||
    diffusions = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for schedule in schedules:
 | 
					 | 
				
			||||||
        dates = schedule.dates_of_month()
 | 
					 | 
				
			||||||
        for date in dates:
 | 
					 | 
				
			||||||
            diffusion = Diffusion.objects \
 | 
					 | 
				
			||||||
                         .filter(date = date, parent__parent = schedule.parent)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if diffusion.count():
 | 
					 | 
				
			||||||
                if not unsaved_only:
 | 
					 | 
				
			||||||
                    diffusions.append(diffusion)
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # get episode
 | 
					 | 
				
			||||||
            ep_date = date
 | 
					 | 
				
			||||||
            if schedule.rerun:
 | 
					 | 
				
			||||||
                ep_date = schedule.rerun.date
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            episode = Episode.objects().filter( date = ep_date
 | 
					 | 
				
			||||||
                                              , parent = schedule.parent )
 | 
					 | 
				
			||||||
            episode  = episode[0] if episode.count() else None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # make diffusion
 | 
					 | 
				
			||||||
            diffusion = Diffusion( parent = episode
 | 
					 | 
				
			||||||
                         , program = schedule.parent
 | 
					 | 
				
			||||||
                         , type = DiffusionType['diffuse']
 | 
					 | 
				
			||||||
                         , date = date
 | 
					 | 
				
			||||||
                         , stream = settings.AIRCOX_SCHEDULED_STREAM
 | 
					 | 
				
			||||||
                         , scheduled = True
 | 
					 | 
				
			||||||
                         )
 | 
					 | 
				
			||||||
            diffusion.program = schedule.program
 | 
					 | 
				
			||||||
            diffusions.append(diffusion)
 | 
					 | 
				
			||||||
    return diffusions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										7
									
								
								templates/admin/base_site.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								templates/admin/base_site.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{% extends "admin/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block extrahead %}
 | 
				
			||||||
 | 
					    <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.js" type="text/javascript"></script> -->
 | 
				
			||||||
 | 
					    {% include 'autocomplete_light/static.html' %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user