Skip to content

Commit

Permalink
[-] Various updates
Browse files Browse the repository at this point in the history
- explicit admin urls
- django 1.9 compatibility
  - get_formsets was removed
  - admin views needs extra args (args, kwargs)
- more specific obj-data url
  • Loading branch information
jsoa committed Dec 5, 2016
1 parent 2ebc1cc commit 2408809
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 58 deletions.
70 changes: 44 additions & 26 deletions genericadmin/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from functools import update_wrapper

from django.core.urlresolvers import reverse, NoReverseMatch
from django.contrib import admin
from django.conf.urls import url
from django.conf import settings
Expand All @@ -12,7 +13,7 @@

from django.contrib.contenttypes.models import ContentType
try:
from django.utils.encoding import force_text
from django.utils.encoding import force_text
except ImportError:
from django.utils.encoding import force_unicode as force_text
from django.utils.text import capfirst
Expand All @@ -24,7 +25,7 @@
from django.contrib.admin.options import IS_POPUP_VAR
from django.core.exceptions import ObjectDoesNotExist

JS_PATH = getattr(settings, 'GENERICADMIN_JS', 'genericadmin/js/')
JS_PATH = getattr(settings, 'GENERICADMIN_JS', 'genericadmin/js/')

class BaseGenericModelAdmin(object):
class Media:
Expand All @@ -34,26 +35,26 @@ class Media:
generic_fk_fields = []
content_type_blacklist = []
content_type_whitelist = []

def __init__(self, model, admin_site):
try:
media = list(self.Media.js)
except:
media = []
media.append(JS_PATH + 'genericadmin.js')
self.Media.js = tuple(media)

self.content_type_whitelist = [s.lower() for s in self.content_type_whitelist]
self.content_type_blacklist = [s.lower() for s in self.content_type_blacklist]
self.content_type_blacklist = [s.lower() for s in self.content_type_blacklist]

super(BaseGenericModelAdmin, self).__init__(model, admin_site)

def get_generic_field_list(self, request, prefix=''):
if hasattr(self, 'ct_field') and hasattr(self, 'ct_fk_field'):
exclude = [self.ct_field, self.ct_fk_field]
else:
exclude = []

field_list = []
if hasattr(self, 'generic_fk_fields') and self.generic_fk_fields:
for fields in self.generic_fk_fields:
Expand All @@ -62,19 +63,26 @@ def get_generic_field_list(self, request, prefix=''):
fields['inline'] = prefix != ''
fields['prefix'] = prefix
field_list.append(fields)
else:
else:
for field in self.model._meta.virtual_fields:
if isinstance(field, GenericForeignKey) and \
field.ct_field not in exclude and field.fk_field not in exclude:
field_list.append({
'ct_field': field.ct_field,
'ct_field': field.ct_field,
'fk_field': field.fk_field,
'inline': prefix != '',
'prefix': prefix,
})

if hasattr(self, 'inlines') and len(self.inlines) > 0:
for FormSet, inline in zip(self.get_formsets(request), self.get_inline_instances(request)):
try:
# Django < 1.9
formsets = zip(self.get_formsets(request), self.get_inline_instances(request))
except (AttributeError, ):
# Django >= 1.9
formsets = self.get_formsets_with_inlines(request)

for FormSet, inline in formsets:
if hasattr(inline, 'get_generic_field_list'):
prefix = FormSet.get_default_prefix()
field_list = field_list + inline.get_generic_field_list(request, prefix)
Expand All @@ -86,26 +94,36 @@ def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)

custom_urls = [
url(r'^obj-data/$', wrap(self.generic_lookup), name='admin_genericadmin_obj_lookup'),
url(r'^genericadmin-init/$', wrap(self.genericadmin_js_init), name='admin_genericadmin_init'),
url(r'^(.*)genericadmin-obj-data/', wrap(
self.generic_lookup), name='admin_genericadmin_obj_lookup'),
url(r'^(.*)genericadmin-init/', wrap(
self.genericadmin_js_init), name='admin_genericadmin_init'),
]
return custom_urls + super(BaseGenericModelAdmin, self).get_urls()
def genericadmin_js_init(self, request):

def genericadmin_js_init(self, request, *args, **kwargs):
if request.method == 'GET':
obj_dict = {}
for c in ContentType.objects.all():
val = force_text('%s/%s' % (c.app_label, c.model))
params = self.content_type_lookups.get('%s.%s' % (c.app_label, c.model), {})
params = url_params_from_lookup_dict(params)

try:
# Reverse the admin changelist url
url = reverse('admin:%s_%s_changelist' % (
c.app_label, c.model))
except (NoReverseMatch, ):
continue

if self.content_type_whitelist:
if val in self.content_type_whitelist:
obj_dict[c.id] = (val, params)
obj_dict[c.id] = (val, url, params)
elif val not in self.content_type_blacklist:
obj_dict[c.id] = (val, params)
obj_dict[c.id] = (val, url, params)

data = {
'url_array': obj_dict,
'fields': self.get_generic_field_list(request),
Expand All @@ -114,15 +132,15 @@ def genericadmin_js_init(self, request):
resp = json.dumps(data, ensure_ascii=False)
return HttpResponse(resp, content_type='application/json')
return HttpResponseNotAllowed(['GET'])
def generic_lookup(self, request):

def generic_lookup(self, request, *args, **kwargs):
if request.method != 'GET':
return HttpResponseNotAllowed(['GET'])

if 'content_type' in request.GET and 'object_id' in request.GET:
content_type_id = request.GET['content_type']
object_id = request.GET['object_id']

obj_dict = {
'content_type_id': content_type_id,
'object_id': object_id,
Expand All @@ -136,20 +154,20 @@ def generic_lookup(self, request):
obj_dict["object_text"] = capfirst(force_text(obj))
except ObjectDoesNotExist:
raise Http404

resp = json.dumps(obj_dict, ensure_ascii=False)
else:
resp = ''
return HttpResponse(resp, content_type='application/json')



class GenericAdminModelAdmin(BaseGenericModelAdmin, admin.ModelAdmin):
"""Model admin for generic relations. """


class GenericTabularInline(BaseGenericModelAdmin, GenericTabularInline):
"""Model admin for generic tabular inlines. """
"""Model admin for generic tabular inlines. """


class GenericStackedInline(BaseGenericModelAdmin, GenericStackedInline):
Expand Down
67 changes: 35 additions & 32 deletions genericadmin/static/genericadmin/js/genericadmin.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
var GenericAdmin = {
url_array: null,
fields: null,
obj_url: "../obj-data/",
obj_url: "../genericadmin-obj-data/",
admin_media_url: window.__admin_media_prefix__,
popup: '_popup',

prepareSelect: function(select) {
var that = this,
opt_keys = [],
Expand All @@ -30,7 +30,7 @@
if (this.value) {
if (that.url_array[this.value]) {
key = that.url_array[this.value][0].split('/')[0];

opt = $(this).clone();
opt.text(that.capFirst(opt.text()));
if ($.inArray(key, opt_keys) < 0) {
Expand All @@ -47,7 +47,7 @@
}
});
select.empty().append(no_value);

opt_keys = opt_keys.sort();

$.each(opt_keys, function(index, key) {
Expand All @@ -61,8 +61,9 @@
return select;
},


getLookupUrlParams: function(cID) {
var q = this.url_array[cID][1] || {},
var q = this.url_array[cID][2] || {},
str = [];
for(var p in q) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(q[p]));
Expand All @@ -71,52 +72,54 @@
url = x ? ("?" + x) : "";
return url;
},

getLookupUrl: function(cID) {
return '../../../' + this.url_array[cID][0] + '/' + this.getLookupUrlParams(cID);

getLookupUrl: function(cID, with_params) {
var url = this.url_array[cID][1];
if(with_params){url = url + this.getLookupUrlParams(cID);}
return url;
},

getFkId: function() {
if (this.fields.inline === false) {
return 'id_' + this.fields.fk_field;
} else {
return ['id_', this.fields.prefix, '-', this.fields.number, '-', this.fields.fk_field].join('');
}
},

getCtId: function() {
if (this.fields.inline === false) {
return 'id_' + this.fields.ct_field;
} else {
return ['id_', this.fields.prefix, '-', this.fields.number, '-', this.fields.ct_field].join('');
}
},

capFirst: function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
},

hideLookupLink: function() {
var this_id = this.getFkId();
$('#lookup_' + this_id).unbind().remove();
$('#lookup_text_' + this_id + ' a').remove();
$('#lookup_text_' + this_id + ' span').remove();
},

showLookupLink: function() {
var that = this,
url = this.getLookupUrl(this.cID),
url = this.getLookupUrl(this.cID, true),
id = 'lookup_' + this.getFkId(),
link = '<a class="related-lookup" id="' + id + '" href="' + url + '">&nbsp;</a>';

link = link + '<strong id="lookup_text_'+ this.getFkId() +'" margin-left: 5px"><a target="_new" href="#"></a><span></span></strong>';

// insert link html after input element
this.object_input.after(link);

return id;
},

pollInputChange: function(window) {
var that = this,
interval_id = setInterval(function() {
Expand All @@ -128,11 +131,11 @@
},
150);
},

popRelatedObjectLookup: function(link) {
var name = id_to_windowname(this.getFkId()),
url_parts = [],
href,
href,
win;

if (link.href.search(/\?/) >= 0) {
Expand All @@ -156,14 +159,14 @@
win.focus();
return false;
},

updateObjectData: function() {
var that = this;
return function() {
var value = that.object_input.val();
if (!value) {
return

if (!value) {
return
}
//var this_id = that.getFkId();
$('#lookup_text_' + that.getFkId() + ' span').text('loading...');
Expand All @@ -176,7 +179,7 @@
},
success: function(item) {
if (item && item.content_type_text && item.object_text) {
var url = that.getLookupUrl(that.cID);
var url = that.getLookupUrl(that.cID, false);
$('#lookup_text_' + that.getFkId() + ' a')
.text(item.content_type_text + ': ' + item.object_text)
.attr('href', url + item.object_id);
Expand Down Expand Up @@ -208,10 +211,10 @@
this.url_array = url_array;
this.fields = fields;
this.popup = popup_var || this.popup;

// store the base element
this.object_input = $("#" + this.getFkId());

// find the select we need to change
this.object_select = this.prepareSelect($("#" + this.getCtId()));

Expand Down Expand Up @@ -245,22 +248,22 @@
this.updateObjectData()();
}
};

var InlineAdmin = {
sub_admins: null,
url_array: null,
fields: null,
popup: '_popup',

install: function(fields, url_array, popup_var) {
var inline_count = $('#id_' + fields.prefix + '-TOTAL_FORMS').val(),
admin;

this.url_array = url_array;
this.fields = fields;
this.sub_admins = [];
this.popup = popup_var || this.popup;

for (var j = 0; j < inline_count; j++) {
f = $.extend({}, this.fields);
f.number = j;
Expand All @@ -279,7 +282,7 @@
added_fields.number = ($('#id_' + that.fields.prefix + '-TOTAL_FORMS').val() - 1);
admin.install(added_fields, that.url_array, that.popup);
that.sub_admins.push(admin);

$('#' + that.fields.prefix + '-' + added_fields.number + ' .inline-deletelink').click(
that.removeHandler(that)
);
Expand All @@ -290,7 +293,7 @@
var parent_id,
deleted_num,
sub_admin;

e.preventDefault();
parent_id = $(e.currentTarget).parents('.dynamic-' + that.fields.prefix).first().attr('id');
deleted_num = parseInt(parent_id.charAt(parent_id.length - 1), 10);
Expand All @@ -315,7 +318,7 @@
ct_fields = data.fields,
popup_var = data.popup_var,
fields;

for (var i = 0; i < ct_fields.length; i++) {
fields = ct_fields[i];
if (fields.inline === false) {
Expand Down

0 comments on commit 2408809

Please sign in to comment.