work on admin interface
This commit is contained in:
		
							
								
								
									
										51
									
								
								cms/admin.py
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								cms/admin.py
									
									
									
									
									
								
							@ -4,7 +4,6 @@ from django.utils.translation import ugettext as _, ugettext_lazy
 | 
			
		||||
import aircox.cms.models as models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = [ 'title', 'date', 'author', 'published', 'post_tags']
 | 
			
		||||
    list_editable = [ 'published' ]
 | 
			
		||||
@ -42,6 +41,56 @@ class CommentAdmin(admin.ModelAdmin):
 | 
			
		||||
        return post.content[:256]
 | 
			
		||||
    content_slice.short_description = _('content')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostInline(admin.StackedInline):
 | 
			
		||||
    extra = 1
 | 
			
		||||
    max_num = 1
 | 
			
		||||
    verbose_name = _('Post')
 | 
			
		||||
 | 
			
		||||
    fieldsets = [
 | 
			
		||||
        (None, {
 | 
			
		||||
            'fields': ['title', 'content', 'image', 'tags']
 | 
			
		||||
        }),
 | 
			
		||||
        (None, {
 | 
			
		||||
            'fields': ['date', 'published', 'author']
 | 
			
		||||
        })
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def inject_related_inline(post_model, prepend = False, inline = None):
 | 
			
		||||
    """
 | 
			
		||||
    Create an inline class and inject it into the related model admin class.
 | 
			
		||||
    Clean-up bound attributes.
 | 
			
		||||
    """
 | 
			
		||||
    class InlineModel(PostInline):
 | 
			
		||||
        model = post_model
 | 
			
		||||
        verbose_name = _('Related post')
 | 
			
		||||
 | 
			
		||||
    inline = inline or InlineModel
 | 
			
		||||
 | 
			
		||||
    # remove bound attributes
 | 
			
		||||
    for none, dic in inline.fieldsets:
 | 
			
		||||
        if not dic.get('fields'):
 | 
			
		||||
            continue
 | 
			
		||||
        dic['fields'] = [ v for v in dic['fields']
 | 
			
		||||
                            if v not in post_model._relation.bindings.keys() ]
 | 
			
		||||
 | 
			
		||||
    inject_inline(post_model._meta.get_field('related').rel.to,
 | 
			
		||||
                  inline, prepend)
 | 
			
		||||
 | 
			
		||||
def inject_inline(model, inline, prepend = False):
 | 
			
		||||
    registry = admin.site._registry
 | 
			
		||||
    if not model in registry:
 | 
			
		||||
        return TypeError('{} not in admin registry'.format(model.__name__))
 | 
			
		||||
 | 
			
		||||
    inlines = list(registry[model].inlines) or []
 | 
			
		||||
    if prepend:
 | 
			
		||||
        inlines.insert(0, inline)
 | 
			
		||||
    else:
 | 
			
		||||
        inlines.append(inline)
 | 
			
		||||
    registry[model].inlines = inlines
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(models.Article, PostAdmin)
 | 
			
		||||
admin.site.register(models.Comment, CommentAdmin)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -288,7 +288,8 @@ class RelatedPostBase (models.base.ModelBase):
 | 
			
		||||
            post = model.objects.filter(related = instance)
 | 
			
		||||
            if post.count():
 | 
			
		||||
                post = post[0]
 | 
			
		||||
            elif rel.auto_create:
 | 
			
		||||
            elif rel.auto_create(instance) if callable(rel.auto_create) else \
 | 
			
		||||
                 rel.auto_create:
 | 
			
		||||
                post = model(related = instance)
 | 
			
		||||
            else:
 | 
			
		||||
                return
 | 
			
		||||
@ -375,12 +376,12 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
			
		||||
        * post_to_rel: auto update related object when post is updated
 | 
			
		||||
        * rel_to_post: auto update the post when related object is updated
 | 
			
		||||
        * thread_model: generated by the metaclass, points to the RelatedPost
 | 
			
		||||
            model generated for the bindings.thread object.
 | 
			
		||||
          model generated for the bindings.thread object.
 | 
			
		||||
        * field_args: dict of arguments to pass to the ForeignKey constructor,
 | 
			
		||||
            such as: ForeignKey(related_model, **field_args)
 | 
			
		||||
          such as: ForeignKey(related_model, **field_args)
 | 
			
		||||
        * auto_create: automatically create a RelatedPost for each new item of
 | 
			
		||||
            the related object and init it with bounded values. Use signals
 | 
			
		||||
            '', ''.
 | 
			
		||||
          the related object and init it with bounded values. Use 'post_save'
 | 
			
		||||
          signal. If auto_create is callable, use `auto_create(related_object)`.
 | 
			
		||||
 | 
			
		||||
        Be careful with post_to_rel!
 | 
			
		||||
        * There is no check of permissions when related object is synchronised
 | 
			
		||||
 | 
			
		||||
@ -11,22 +11,22 @@ from aircox.programs.models import *
 | 
			
		||||
#
 | 
			
		||||
# Inlines
 | 
			
		||||
#
 | 
			
		||||
class SoundInline (admin.TabularInline):
 | 
			
		||||
class SoundInline(admin.TabularInline):
 | 
			
		||||
    model = Sound
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ScheduleInline (admin.TabularInline):
 | 
			
		||||
class ScheduleInline(admin.TabularInline):
 | 
			
		||||
    model = Schedule
 | 
			
		||||
    extra = 1
 | 
			
		||||
 | 
			
		||||
class StreamInline (admin.TabularInline):
 | 
			
		||||
class StreamInline(admin.TabularInline):
 | 
			
		||||
    fields = ['delay', 'begin', 'end']
 | 
			
		||||
    model = Stream
 | 
			
		||||
    extra = 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# from suit.admin import SortableTabularInline, SortableModelAdmin
 | 
			
		||||
#class TrackInline (SortableTabularInline):
 | 
			
		||||
#class TrackInline(SortableTabularInline):
 | 
			
		||||
#    fields = ['artist', 'name', 'tags', 'position']
 | 
			
		||||
#    form = TrackForm
 | 
			
		||||
#    model = Track
 | 
			
		||||
@ -34,7 +34,7 @@ class StreamInline (admin.TabularInline):
 | 
			
		||||
#    extra = 10
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NameableAdmin (admin.ModelAdmin):
 | 
			
		||||
class NameableAdmin(admin.ModelAdmin):
 | 
			
		||||
    fields = [ 'name' ]
 | 
			
		||||
 | 
			
		||||
    list_display = ['id', 'name']
 | 
			
		||||
@ -43,7 +43,7 @@ class NameableAdmin (admin.ModelAdmin):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Sound)
 | 
			
		||||
class SoundAdmin (NameableAdmin):
 | 
			
		||||
class SoundAdmin(NameableAdmin):
 | 
			
		||||
    fields = None
 | 
			
		||||
    list_display = ['id', 'name', 'duration', 'type', 'mtime', 'good_quality', 'removed', 'public']
 | 
			
		||||
    fieldsets = [
 | 
			
		||||
@ -55,17 +55,17 @@ class SoundAdmin (NameableAdmin):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Stream)
 | 
			
		||||
class StreamAdmin (admin.ModelAdmin):
 | 
			
		||||
class StreamAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('id', 'program', 'delay', 'begin', 'end')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Station)
 | 
			
		||||
class StationAdmin (NameableAdmin):
 | 
			
		||||
class StationAdmin(NameableAdmin):
 | 
			
		||||
    fields = NameableAdmin.fields + [ 'active', 'public', 'fallback' ]
 | 
			
		||||
 | 
			
		||||
@admin.register(Program)
 | 
			
		||||
class ProgramAdmin (NameableAdmin):
 | 
			
		||||
    def schedule (self, obj):
 | 
			
		||||
class ProgramAdmin(NameableAdmin):
 | 
			
		||||
    def schedule(self, obj):
 | 
			
		||||
        return Schedule.objects.filter(program = obj).count() > 0
 | 
			
		||||
    schedule.boolean = True
 | 
			
		||||
    schedule.short_description = _("Schedule")
 | 
			
		||||
@ -76,7 +76,7 @@ class ProgramAdmin (NameableAdmin):
 | 
			
		||||
    inlines = [ ScheduleInline, StreamInline ]
 | 
			
		||||
 | 
			
		||||
    # SO#8074161
 | 
			
		||||
    #def get_form (self, request, obj=None, **kwargs):
 | 
			
		||||
    #def get_form(self, request, obj=None, **kwargs):
 | 
			
		||||
        #if obj:
 | 
			
		||||
        #    if Schedule.objects.filter(program = obj).count():
 | 
			
		||||
        #        self.inlines.remove(StreamInline)
 | 
			
		||||
@ -84,22 +84,38 @@ class ProgramAdmin (NameableAdmin):
 | 
			
		||||
        #        self.inlines.remove(ScheduleInline)
 | 
			
		||||
        #return super().get_form(request, obj, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionInline(admin.StackedInline):
 | 
			
		||||
    model = Diffusion
 | 
			
		||||
    extra = 0
 | 
			
		||||
    fields = ['type', 'start', 'end']
 | 
			
		||||
 | 
			
		||||
@admin.register(Diffusion)
 | 
			
		||||
class DiffusionAdmin (admin.ModelAdmin):
 | 
			
		||||
    def archives (self, obj):
 | 
			
		||||
class DiffusionAdmin(admin.ModelAdmin):
 | 
			
		||||
    def archives(self, obj):
 | 
			
		||||
        sounds = [ str(s) for s in obj.get_archives()]
 | 
			
		||||
        return ', '.join(sounds) if sounds else ''
 | 
			
		||||
 | 
			
		||||
    def conflicts (self, obj):
 | 
			
		||||
    def conflicts(self, obj):
 | 
			
		||||
        if obj.type == Diffusion.Type.unconfirmed:
 | 
			
		||||
            return ', '.join([ str(d) for d in obj.get_conflicts()])
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
    list_display = ('id', 'type', 'start', 'end', 'program', 'initial', 'archives', 'conflicts')
 | 
			
		||||
    def end_time(self, obj):
 | 
			
		||||
        return obj.end.strftime('%H:%M')
 | 
			
		||||
    end_time.short_description = _('end')
 | 
			
		||||
 | 
			
		||||
    def first(self, obj):
 | 
			
		||||
        return obj.initial.start if obj.initial else ''
 | 
			
		||||
 | 
			
		||||
    list_display = ('id', 'program', 'start', 'end_time', 'type', 'first', 'archives', 'conflicts')
 | 
			
		||||
    list_filter = ('type', 'start', 'program')
 | 
			
		||||
    list_editable = ('type', 'start', 'end')
 | 
			
		||||
    list_editable = ('type',)
 | 
			
		||||
    ordering = ('-start', 'id')
 | 
			
		||||
 | 
			
		||||
    fields = ['type', 'start', 'end', 'initial', 'program', 'sounds']
 | 
			
		||||
    inlines = [ DiffusionInline ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_form(self, request, obj=None, **kwargs):
 | 
			
		||||
        if request.user.has_perm('aircox_program.programming'):
 | 
			
		||||
@ -111,32 +127,40 @@ class DiffusionAdmin (admin.ModelAdmin):
 | 
			
		||||
            self.readonly_fields += ['program', 'sounds']
 | 
			
		||||
        return super().get_form(request, obj, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_object(self, *args, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        We want rerun to redirect to the given object.
 | 
			
		||||
        """
 | 
			
		||||
        obj = super().get_object(*args, **kwargs)
 | 
			
		||||
        if obj.initial:
 | 
			
		||||
            obj = obj.initial
 | 
			
		||||
        return obj
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self, request):
 | 
			
		||||
        qs = super(DiffusionAdmin, self).get_queryset(request)
 | 
			
		||||
        if ('_changelist_filters' in request.GET or \
 | 
			
		||||
            'type__exact' in request.GET) and \
 | 
			
		||||
                str(Diffusion.Type.unconfirmed) in request.GET['type__exact']:
 | 
			
		||||
        qs = super().get_queryset(request)
 | 
			
		||||
        if request.GET and '_changelist_filters' in request.GET and \
 | 
			
		||||
                request.GET.get('type__exact') == Diffusion.Type.unconfirmed:
 | 
			
		||||
            return qs
 | 
			
		||||
        return qs.exclude(type = Diffusion.Type.unconfirmed)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Log)
 | 
			
		||||
class LogAdmin (admin.ModelAdmin):
 | 
			
		||||
class LogAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ['id', 'date', 'source', 'comment', 'related_object']
 | 
			
		||||
    list_filter = ['date', 'source', 'related_type']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Schedule)
 | 
			
		||||
class ScheduleAdmin (admin.ModelAdmin):
 | 
			
		||||
    def program_name (self, obj):
 | 
			
		||||
class ScheduleAdmin(admin.ModelAdmin):
 | 
			
		||||
    def program_name(self, obj):
 | 
			
		||||
        return obj.program.name
 | 
			
		||||
    program_name.short_description = _('Program')
 | 
			
		||||
 | 
			
		||||
    def day (self, obj):
 | 
			
		||||
    def day(self, obj):
 | 
			
		||||
        return obj.date.strftime('%A')
 | 
			
		||||
    day.short_description = _('Day')
 | 
			
		||||
 | 
			
		||||
    def rerun (self, obj):
 | 
			
		||||
    def rerun(self, obj):
 | 
			
		||||
        return obj.initial != None
 | 
			
		||||
    rerun.short_description = _('Rerun')
 | 
			
		||||
    rerun.boolean = True
 | 
			
		||||
 | 
			
		||||
@ -7,19 +7,17 @@ import aircox.website.models as models
 | 
			
		||||
import aircox.website.forms as forms
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TrackInline (SortableTabularInline):
 | 
			
		||||
class TrackInline(SortableTabularInline):
 | 
			
		||||
    fields = ['artist', 'name', 'tags', 'position']
 | 
			
		||||
    form = forms.TrackForm
 | 
			
		||||
    model = programs.Track
 | 
			
		||||
    sortable = 'position'
 | 
			
		||||
    extra = 10
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionPostAdmin(cms.RelatedPostAdmin):
 | 
			
		||||
    inlines = [TrackInline]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(models.Program, cms.RelatedPostAdmin)
 | 
			
		||||
admin.site.register(models.Diffusion, DiffusionPostAdmin)
 | 
			
		||||
admin.site.register(models.Diffusion, cms.RelatedPostAdmin)
 | 
			
		||||
 | 
			
		||||
cms.inject_inline(programs.Diffusion, TrackInline, True)
 | 
			
		||||
cms.inject_related_inline(models.Diffusion, True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
from django import forms
 | 
			
		||||
 | 
			
		||||
import autocomplete_light.shortcuts as al
 | 
			
		||||
from autocomplete_light.contrib.taggit_field import TaggitWidget
 | 
			
		||||
#import autocomplete_light.shortcuts as al
 | 
			
		||||
#from autocomplete_light.contrib.taggit_field import TaggitWidget
 | 
			
		||||
 | 
			
		||||
import aircox.programs.models as programs
 | 
			
		||||
 | 
			
		||||
@ -11,9 +11,9 @@ class TrackForm (forms.ModelForm):
 | 
			
		||||
        model = programs.Track
 | 
			
		||||
        fields = ['artist', 'name', 'tags', 'position']
 | 
			
		||||
        widgets = {
 | 
			
		||||
            'artist': al.TextWidget('TrackArtistAutocomplete'),
 | 
			
		||||
            'name': al.TextWidget('TrackNameAutocomplete'),
 | 
			
		||||
            'tags': TaggitWidget('TagAutocomplete'),
 | 
			
		||||
#            'artist': al.TextWidget('TrackArtistAutocomplete'),
 | 
			
		||||
#            'name': al.TextWidget('TrackNameAutocomplete'),
 | 
			
		||||
#            'tags': TaggitWidget('TagAutocomplete'),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,9 @@ class Diffusion (RelatedPost):
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        rel_to_post = True
 | 
			
		||||
        auto_create = True
 | 
			
		||||
 | 
			
		||||
        def auto_create(object):
 | 
			
		||||
            return not object.initial
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user