Merge branch '0.4'

This commit is contained in:
Corey Oordt 2010-04-23 14:06:08 -04:00
commit cc25aabe3d
16 changed files with 199 additions and 7 deletions

View file

@ -1,11 +1,14 @@
from models import Category
from django.contrib import admin
from django import forms
from django.template.defaultfilters import slugify
from mptt.forms import TreeNodeChoiceField
from editor.tree_editor import TreeEditor
from settings import ALLOW_SLUG_CHANGE
from genericcollection import GenericCollectionTabularInline
from settings import ALLOW_SLUG_CHANGE, RELATION_MODELS
from categories import registry
from models import Category
class NullTreeNodeChoiceField(forms.ModelChoiceField):
"""A ModelChoiceField for tree nodes."""
@ -21,6 +24,11 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField):
"""
return u'%s %s' % (self.level_indicator * getattr(obj, obj._meta.level_attr),
obj)
if RELATION_MODELS:
from models import CategoryRelation
class InlineCategoryRelation(GenericCollectionTabularInline):
model = CategoryRelation
class CategoryAdminForm(forms.ModelForm):
@ -84,7 +92,12 @@ class CategoryAdmin(TreeEditor, admin.ModelAdmin):
'classes': ('collapse',),
}),
)
if RELATION_MODELS:
inlines = [InlineCategoryRelation,]
class Media:
js = ('js/genericcollections.js',)
admin.site.register(Category, CategoryAdmin)

View file

@ -0,0 +1,25 @@
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin):
ct_field = "content_type"
ct_fk_field = "object_id"
def __init__(self, parent_model, admin_site):
super(GenericCollectionInlineModelAdmin, self).__init__(parent_model, admin_site)
ctypes = ContentType.objects.all().order_by('id').values_list('id', 'app_label', 'model')
elements = ["%s: '%s/%s'" % (x, y, z) for x, y, z in ctypes]
self.content_types = "{%s}" % ",".join(elements)
def get_formset(self, request, obj=None):
result = super(GenericCollectionInlineModelAdmin, self).get_formset(request, obj)
result.content_types = self.content_types
result.ct_fk_field = self.ct_fk_field
return result
class GenericCollectionTabularInline(GenericCollectionInlineModelAdmin):
template = 'admin/edit_inline/gen_coll_tabular.html'
class GenericCollectionStackedInline(GenericCollectionInlineModelAdmin):
template = 'admin/edit_inline/gen_coll_stacked.html'

View file

@ -0,0 +1,20 @@
function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) {
var realName = triggeringLink.id.replace(/^lookup_/, '');
var name = id_to_windowname(realName);
realName = realName.replace(/object_id/, 'content_type');
var select = document.getElementById(realName);
if (select.selectedIndex === 0) {
alert("Select a content type first.");
return false;
}
var selectedItem = select.item(select.selectedIndex).value;
var href = triggeringLink.href.replace(/#/,'../../../'+ctArray[selectedItem]+"/?t=id");
if (href.search(/\?/) >= 0) {
href = href + '&pop=1';
} else {
href = href + '?pop=1';
}
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}

View file

@ -3,8 +3,14 @@ from django.core.urlresolvers import reverse
from django.db.models import permalink
from django.db import models
from django.utils.encoding import force_unicode
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext as _
import mptt
from settings import RELATION_MODELS, RELATIONS
class Category(models.Model):
parent = models.ForeignKey('self',
blank=True,
@ -49,3 +55,32 @@ class Category(models.Model):
return ' > '.join([force_unicode(i.name) for i in ancestors]+[self.name,])
mptt.register(Category, order_insertion_by=['name'])
if RELATION_MODELS:
category_relation_limits = reduce(lambda x,y: x|y, RELATIONS)
class CategoryRelationManager(models.Manager):
def get_content_type(self, content_type):
qs = self.get_query_set()
return qs.filter(content_type__name=content_type)
def get_relation_type(self, relation_type):
qs = self.get_query_set()
return qs.filter(relation_type=relation_type)
class CategoryRelation(models.Model):
"""Related story item"""
story = models.ForeignKey(Category)
content_type = models.ForeignKey(ContentType, limit_choices_to=category_relation_limits)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
relation_type = models.CharField(_("Relation Type"),
max_length="200",
blank=True,
null=True,
help_text=_("A generic text field to tag a relation, like 'leadphoto'."))
objects = CategoryRelationManager()
def __unicode__(self):
return u"CategoryRelation"

View file

@ -2,4 +2,9 @@ from django.conf import settings
ALLOW_SLUG_CHANGE = getattr(settings, 'CATEGORIES_ALLOW_SLUG_CHANGE', False)
CACHE_VIEW_LENGTH = getattr(settings, 'CATEGORIES_CACHE_VIEW_LENGTH', 3600)
CACHE_VIEW_LENGTH = getattr(settings, 'CATEGORIES_CACHE_VIEW_LENGTH', 3600)
from django.db.models import Q
DEFAULT_RELATION_MODELS = []
RELATION_MODELS = getattr(settings, 'CATEGORIES_RELATION_MODELS', DEFAULT_RELATION_MODELS) or []
RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split('.') for x in RELATION_MODELS]]

View file

@ -0,0 +1,68 @@
{% load i18n adminmedia %}
<div class="inline-group">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }}
<fieldset class="module">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
{{ inline_admin_formset.formset.non_form_errors }}
<table>
<thead><tr>
{% for field in inline_admin_formset.fields %}
<th {% if forloop.first %}colspan="2"{% endif %}>{{ field.label|capfirst }}</th>
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
</tr></thead>
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
<tr><td colspan="{{ inline_admin_form.field_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %}
<tr class="{% cycle row1,row2 %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}">
<td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original.content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
</p>{% endif %}
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% spaceless %}
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endspaceless %}
</td>
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
<td class="{{ field.field.name }}">
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field.errors.as_ul }}
{% ifequal field.field.name inline_admin_formset.formset.ct_fk_field %}
{{ field.field }}
<a id="lookup_id_{{field.field.html_name}}" class="related-lookup" onclick="return showGenericRelatedObjectLookupPopup(this, {{ inline_admin_formset.formset.content_types }});" href="#">
<img width="16" height="16" alt="Lookup" src="{% admin_media_prefix %}img/admin/selector-search.gif"/>
</a>
{% else %}{{ field.field }} {% endifequal %}
{% endif %}
</td>
{% endfor %}
{% endfor %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}
<td class="delete">
{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
</div>
</div>

View file

@ -38,7 +38,7 @@ USE_I18N = True
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = APP + '/static/'
MEDIA_ROOT = APP + '/media/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
@ -66,7 +66,7 @@ MIDDLEWARE_CLASSES = (
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
ROOT_URLCONF = 'sample.urls'
ROOT_URLCONF = 'example.urls'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
@ -80,10 +80,12 @@ INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.flatpages',
'categories',
'editor',
'mptt',
'simpletext',
)
EDITOR_MEDIA_PATH = '/static/editor/'
CATEGORIES_ALLOW_SLUG_CHANGE = True
CATEGORIES_ALLOW_SLUG_CHANGE = True
CATEGORIES_RELATION_MODELS = ['simpletext.simpletext','flatpages.flatpage']

View file

@ -0,0 +1,20 @@
function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) {
var realName = triggeringLink.id.replace(/^lookup_/, '');
var name = id_to_windowname(realName);
realName = realName.replace(/object_id/, 'content_type');
var select = document.getElementById(realName);
if (select.selectedIndex === 0) {
alert("Select a content type first.");
return false;
}
var selectedItem = select.item(select.selectedIndex).value;
var href = triggeringLink.href.replace(/#/,'../../../'+ctArray[selectedItem]+"/?t=id");
if (href.search(/\?/) >= 0) {
href = href + '&pop=1';
} else {
href = href + '?pop=1';
}
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}

View file

@ -28,4 +28,8 @@ urlpatterns = patterns('',
(r'^static/editor/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': ROOT_PATH + '/editor/media/editor/',
'show_indexes':True}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': ROOT_PATH + '/example/static/'}),
)