source: cyclope/core/collections/admin.py @ 232:7b4b4d05de94

Revision 232:7b4b4d05de94, 7.5 KB checked in by nicoechaniz <nico@…>, 3 years ago (diff)

added default view to Collection

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright 2010 Código Sur - Nuestra América Asoc. Civil / Fundación Pacificar.
5# All rights reserved.
6#
7# This file is part of Cyclope.
8#
9# Cyclope is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# Cyclope is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22"""
23core.collections.admin
24----------------------
25"""
26
27from django.contrib import admin
28from django.utils.translation import ugettext_lazy as _
29from django import forms
30from django.db.models import get_model
31from django.contrib.contenttypes import generic
32from django.db import models
33
34from mptt.forms import TreeNodeChoiceField
35from feincms.admin import editor
36
37from cyclope.widgets import WYMEditor
38from cyclope.core import frontend
39
40from models import *
41from cyclope.models import Menu
42from cyclope import settings as cyc_settings
43
44####
45# custom FilterSpec
46# based on snippet found at:
47# http://www.djangosnippets.org/snippets/1051/
48# This is a workaround to add a custom filter to the admin changelist
49# until a generic way of adding custom filter specs make it into django.
50# See ticket: http://code.djangoproject.com/ticket/5833
51####
52
53from django.db import models
54from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
55from django.utils.encoding import smart_unicode
56
57class CategoryFilterSpec(ChoicesFilterSpec):
58    """Adds filtering by categories.
59
60    To be used by Collectible based objects.
61
62    categories.category_filter must be set to True in the model
63    for this filter to be active.
64    """
65
66    def __init__(self, f, request, params, model, model_admin):
67        super(CategoryFilterSpec, self).__init__(f, request, params, model,
68                                                   model_admin)
69
70        self.lookup_kwarg = 'categories__category__slug'
71        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
72
73        object_ctype = ContentType.objects.get_for_model(model)
74
75        # select categories available for the content type of the object
76        qs = Category.tree.filter(collection__content_types=object_ctype)
77        # create list of choices and the corresponding indented labels
78        self.lookup_choices = [(item.slug, u'%s%s' % \
79                                ('-'* item.level, item.name)) \
80                                for item in qs ]
81        self.model = model
82
83    def choices(self, cl):
84        # show All items when no choice is selected
85        yield {'selected': self.lookup_val is None,
86                'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
87                'display': _('All')}
88        for [val, display] in self.lookup_choices:
89            yield {'selected': smart_unicode(val) == self.lookup_val,
90                  'query_string': cl.get_query_string({self.lookup_kwarg: val}),
91                  'display': display}
92
93    def title(self):
94        return _('categories')
95
96FilterSpec.filter_specs.insert(0, (lambda f: \
97                                   getattr(f, 'category_filter', False),
98                                   CategoryFilterSpec))
99####
100
101
102class CategoryForm(forms.ModelForm):
103    description = forms.CharField(label=_('Description'),
104                                  widget=WYMEditor(), required=False)
105    parent = TreeNodeChoiceField(label=_('Parent'),
106                                 queryset=Category.tree.all(), required=False)
107
108    class Meta:
109        model = Category
110
111class CategoryAdmin(editor.TreeEditor):
112    form = CategoryForm
113    list_filter = ['collection']
114    fieldsets = (
115        (None, {
116            'fields': ('collection', 'name', 'parent')
117        }),
118        (_('Extra info'),{
119            'classes': ('collapse',),
120            'fields': ('active', 'description', 'image',),
121        }),
122    )
123    def changelist_view(self, request, extra_context=None):
124        # category changelist should only show items from one collection.
125        # so we activate the filter to display categories from one collection
126        # when no filters have been selected by the user
127        a_collection = Collection.objects.all()[0].id
128        if not request.GET:
129            request.GET = {u'collection__id__exact': unicode(a_collection)}
130        return super(CategoryAdmin, self).changelist_view(request, extra_context)
131
132admin.site.register(Category, CategoryAdmin)
133
134
135class CategorizationForm(forms.ModelForm):
136    # We declare these fields and override their querysets later.
137    collection = forms.ModelChoiceField(
138        label=_('Collection'),
139        queryset=Collection.objects.all().order_by('-name'), required=False)
140    category = TreeNodeChoiceField(label=_('Category'), queryset=None, required=True)
141
142    def __init__(self, *args, **kwargs):
143        super(CategorizationForm, self).__init__(*args, **kwargs)
144        if self.instance.id is not None:
145            self.fields['collection'].initial = self.instance.category.collection.pk
146
147
148class CategorizationInline(generic.GenericStackedInline):
149    """Limits choices to those suitable for the content type
150    of the object being created / changed.
151    """
152    form = CategorizationForm
153    model = Categorization
154    extra = 0
155    fieldsets = (
156        (None, {
157            'fields': ('collection', 'category',)
158        }),
159    )
160
161    def queryset(self, request):
162        # TODO(nicoechaniz):We only override the queryset for the category field.
163        # This piece of code is here because we need it to be called
164        # when showing the form. So __init__ can't be used
165        # It still looks like quite "hacky" a place to put it...
166        req_model_ctype = ContentType.objects.get_for_model(self.parent_model)
167
168        self.form.base_fields['category'].queryset = \
169            Category.tree.filter(
170            collection__content_types=req_model_ctype).order_by('collection__name')
171
172        self.form.base_fields['collection'].queryset = \
173            Collection.objects.filter(
174            content_types=req_model_ctype).order_by('name')
175
176        return super(CategorizationInline, self).queryset(request)
177
178
179class CollectibleAdmin (admin.ModelAdmin):
180    """Base admin class for models that inherit from Collectible.
181    """
182    list_filter = ('categories',)
183    inlines = [ CategorizationInline, ]
184
185
186class CollectionAdminForm(forms.ModelForm):
187    raw_id_fields = ['picture',]
188    default_list_view = forms.ChoiceField(label=_('Default category listing view'), required=False)
189
190    def __init__(self, *args, **kwargs):
191        super(CollectionAdminForm, self).__init__(*args, **kwargs)
192        self.fields['content_types'].choices = frontend.site.get_base_ctype_choices()
193        model = get_model('collections', 'category')
194        views = [('', '------')] + [ (view.name, view.verbose_name)
195                                     for view in frontend.site._registry[model]
196                                     if view.name != 'default']
197        self.fields['default_list_view'].choices = views
198
199    class Meta:
200        model = Collection
201
202class CollectionAdmin (admin.ModelAdmin):
203    """Base admin class for models that inherit from Collectible.
204    """
205    form = CollectionAdminForm
206
207admin.site.register(Collection, CollectionAdmin)
Note: See TracBrowser for help on using the repository browser.