Created
February 8, 2011 19:19
-
-
Save acdha/817005 to your computer and use it in GitHub Desktop.
django-tastypie VersionDiffResource helper for django-reversion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends "admin/object_history.html" %} | |
{% load adminmedia %} | |
{% block extrahead %} | |
{{ block.super }} | |
<script src="{% admin_media_prefix %}js/jquery.min.js" type="text/javascript" charset="utf-8"></script> | |
{% endblock %} | |
{% block content %} | |
{{ block.super }} | |
<script type="text/javascript"> | |
jQuery(function ($) { | |
$('<div class="diff"><b class="toggle" style="float:right">Show Changes</b><div class="body">Loading…</div>').insertAfter($("#change-history .comment")); | |
$(".diff .body").hide(); | |
$("#change-history").delegate(".diff .toggle", "click", function() { | |
var $this = $(this); | |
var $body = $(this).siblings(".body"); | |
var diff_loaded = $this.data("diff_loaded"); | |
$body.toggle(); | |
if (!diff_loaded) { | |
$this.data("diff_loaded", true); | |
var version_id = $(this).parents("tr").find('th[scope=row] a').attr("href").replace(/^.*\/([0-9]+)\//, "$1"); | |
var version_diff_url = '/api/v1/versiondiff/' + version_id + '/'; | |
if (version_diff_url) { | |
$.ajax({ | |
url: version_diff_url, | |
success: function (data, status) { | |
$body.empty(); | |
var $dl = $("<dl>").appendTo($body); | |
$.each(data, function (k, v) { | |
$("<dt>").text(v.label).appendTo($dl); | |
$("<dd>").html(v.html).appendTo($dl); | |
}); | |
}, | |
error: function (XMLHttpRequest, textStatus, errorThrown) { | |
$body.empty().text("Unable to load changes from server: " + textStatus); | |
} | |
}); | |
} | |
} | |
}); | |
}); | |
</script> | |
{% endblock content %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class VersionDiffResource(Resource): | |
class Meta: | |
allowed_methods = ('get', ) | |
@property | |
def urls(self): | |
""" | |
VersionDiffResource is weird - it effectively has a composite primary | |
key and disallows listing since that doesn't make sense | |
""" | |
urlpatterns = patterns('', | |
url(r"^(?P<resource_name>%s)/$" % self._meta.resource_name, | |
self.wrap_view('dispatch_list'), name="api_dispatch_list"), | |
url(r"^(?P<resource_name>%s)/set/(?P<pk_list>\w[\w/;-]*)/$" % self._meta.resource_name, | |
self.wrap_view('get_multiple'), name="api_get_multiple"), | |
url(r"^(?P<resource_name>%s)/schema/$" % self._meta.resource_name, | |
self.wrap_view('get_schema'), name="api_get_schema"), | |
url(r"^(?P<resource_name>%s)/(?P<current_version_pk>\d+)/$" % self._meta.resource_name, | |
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), | |
url(r"^(?P<resource_name>%s)/(?P<old_version_pk>\d+)-(?P<current_version_pk>\d+)/$" % self._meta.resource_name, | |
self.wrap_view('dispatch_detail'), name="api_dispatch_diff_history"), | |
) | |
return urlpatterns | |
def get_detail(self, request, **kwargs): | |
current_version_pk = kwargs.get("current_version_pk", None) | |
old_version_pk = kwargs.get("old_version_pk", None) | |
try: | |
current_version = Version.objects.get(pk=current_version_pk) | |
except Version.DoesNotExist: | |
return HttpGone() | |
old_version = None | |
if old_version_pk: | |
try: | |
old_version = Version.objects.get(pk=old_version_pk) | |
except Version.DoesNotExist: | |
return HttpGone() | |
else: | |
# Get the version immediately before this one: | |
try: | |
old_version = Version.objects.order_by("-pk").filter( | |
object_id=current_version.object_id, | |
content_type=current_version.content_type, | |
pk__lt=current_version.pk).latest("pk") | |
except Version.DoesNotExist: | |
pass | |
field_names = [] | |
for f in current_version.object_version.object._meta.fields: | |
if f.name in ('id', 'record_modified'): | |
continue | |
if isinstance(f, JSONField): | |
f_type = "json" | |
elif isinstance(f, django_fields.TextField): | |
f_type = "text" | |
elif isinstance(f, django_fields.related.RelatedField): | |
f_type = "related" | |
else: | |
f_type = "generic" | |
field_names.append((f.name, force_unicode(f.verbose_name), f_type)) | |
diffs = {} | |
if old_version: | |
for name, verbose_name, field_type in field_names: | |
old = force_unicode(old_version.field_dict[name]) | |
current = force_unicode(current_version.field_dict[name]) | |
if field_type in ("text", "json"): | |
if field_type == "json": | |
old = json_pretty(old) | |
current = json_pretty(current) | |
html = pretty_html_diff(old, current) | |
else: | |
# To avoid messy diffs we'll simply display the target but | |
# not actually diff the text values between the two string | |
# representations | |
if field_type == "related": | |
old = getattr(old_version.get_object_version().object, name) | |
current = getattr(current_version.get_object_version().object, name) | |
if old != current: | |
html = u"<del>{0}</del><ins>{1}</ins>".format( | |
escape(old), escape(current)) | |
else: | |
html = force_unicode(current) | |
diffs[name] = { | |
"label": verbose_name, | |
"html": html, | |
} | |
else: | |
obj = current_version.get_object_version().object | |
for k, v, f_type in field_names: | |
diffs[k] = { | |
"label": v, | |
"html": u'<ins>%s</ins>' % getattr(obj, k), | |
} | |
return self.create_response(request, diffs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment