GithubHelp home page GithubHelp logo

jedie / django-reversion-compare Goto Github PK

View Code? Open in Web Editor NEW
313.0 16.0 105.0 1.78 MB

Add compare view to django-reversion for comparing two versions of a reversion model.

Home Page: https://pypi.org/project/django-reversion-compare/

Python 88.38% HTML 11.32% CSS 0.31%
python django reversion

django-reversion-compare's Introduction

django-reversion-compare

tests codecov django-reversion-compare @ PyPi Python Versions License GPL-3.0-or-later

django-reversion-compare is an extension to django-reversion that provides a history compare view to compare two versions of a model which is under reversion.

Comparing model versions is not a easy task. Maybe there are different view how this should looks like. This project will gives you a generic way to see whats has been changed.

Many parts are customizable by overwrite methods or subclassing, see above.

Installation

Just use:

pip install django-reversion-compare

Setup

Add reversion_compare to INSTALLED_APPS in your settings.py, e.g.:

INSTALLED_APPS = (
    'django...',
    ...
    'reversion', # https://github.com/etianen/django-reversion
    'reversion_compare', # https://github.com/jedie/django-reversion-compare
    ...
)

# Add reversion models to admin interface:
ADD_REVERSION_ADMIN=True
# optional settings:
REVERSION_COMPARE_FOREIGN_OBJECTS_AS_ID=False
REVERSION_COMPARE_IGNORE_NOT_REGISTERED=False

Usage

Inherit from CompareVersionAdmin instead of VersionAdmin to get the comparison feature.

admin.py e.g.:

from django.contrib import admin
from reversion_compare.admin import CompareVersionAdmin

from my_app.models import ExampleModel

@admin.register(ExampleModel)
class ExampleModelAdmin(CompareVersionAdmin):
    pass

If you're using an existing third party app, then you can add patch django-reversion-compare into its admin class by using the reversion_compare.helpers.patch_admin() method. For example, to add version control to the built-in User model:

from reversion_compare.helpers import patch_admin

patch_admin(User)

e.g.: Add django-cms Page model:

from cms.models.pagemodel import Page
from reversion_compare.helpers import patch_admin


# Patch django-cms Page Model to add reversion-compare functionality:
patch_admin(Page)

Customize

It's possible to change the look for every field or for a entire field type. You must only define a methods to your admin class with this name scheme:

  • "compare_%s" % field_name
  • "compare_%s" % field.get_internal_type()

If there is no method with this name scheme, the fallback_compare() method will be used.

An example for specifying a compare method for a model field by name:

class YourAdmin(CompareVersionAdmin):
    def compare_foo_bar(self, obj_compare):
        """ compare the foo_bar model field """
        return "%r <-> %r" % (obj_compare.value1, obj_compare.value2)

and example using patch_admin with custom version admin class:

patch_admin(User, AdminClass=YourAdmin)

Class Based View

Beyond the Admin views, you can also create a Class Based View for displaying and comparing version differences. This is a single class-based-view that either displays the list of versions to select for an object or displays both the versions and their differences (if the versions to be compared have been selected). This class can be used just like a normal DetailView:

More information about this can be found in DocString of:

The make run-test-server test project contains a Demo, use the links under:

HistoryCompareDetailView Examples:

Screenshots

Here some screenshots of django-reversion-compare:


How to select the versions to compare:

django-reversion-compare_v0_1_0-01.png


from v0.1.0: DateTimeField compare (last update), TextField compare (content) with small changes and a ForeignKey compare (child model instance was added):

django-reversion-compare_v0_1_0-02.png


from v0.1.0: Same as above, but the are more lines changed in TextField and the ForeignKey relation was removed:

django-reversion-compare_v0_1_0-03.png


Example screenshot from v0.3.0: a many-to-many field compare (friends, hobbies):

django-reversion-compare_v0_3_0-01.png

  • In the first line, the m2m object has been changed.
  • line 2: A m2m object was deleted
  • line 3: A m2m object was removed from this entry (but not deleted)
  • line 4: This m2m object has not changed

create developer environment

We use manage_django_project, so you just need to clone the sources and call manage.py to start hacking.

e.g.:

~$ git clone https://github.com/jedie/django-reversion-compare.git
~$ cd django-reversion-compare

# Just call manage.py and the magic happen:
~/django-reversion-compare$ ./manage.py

# start local dev. web server:
~/django-reversion-compare$ ./manage.py run_dev_server

# run tests:
~/django-reversion-compare$ ./manage.py test
# or with coverage
~/django-reversion-compare$ ./manage.py coverage
# or via tox:
~/django-reversion-compare$ ./manage.py tox p

Backwards-incompatible changes

v0.16.0

We use https://github.com/jedie/manage_django_project to manage the dev venv and we switch to main branch.

You must reinit your dev setup.

v0.12.0

Google "diff-match-patch" is now mandatory and not optional.

Version compatibility

Reversion-Compare django-reversion Django Python
>=v0.17.0 v5.0 (v3.2), v4.2, v5.0 (v3.9), v3.10, v3.11, v3.12
>=v0.16.0 v3.0 v3.2, v4.1, v4.2 v3.9, v3.10, v3.11
>=v0.15.0 v3.0 v2.2, v3.2, v4.0 v3.7, v3.8, v3.9
>=v0.13.0 v3.0 v2.2, v3.0, v3.1 v3.7, v3.8, v3.9
>=v0.10.0 v3.0 v2.2, v3.0 v3.6, v3.7, v3.8, pypy3
>=v0.9.0 v2.0 v2.2, v3.0 v3.6, v3.7, v3.8, pypy3
>=v0.8.6 v2.0 v1.11, v2.0 v3.5, v3.6, v3.7, pypy3
>=v0.8.4 v2.0 v1.8, v1.11, v2.0 v3.5, v3.6, pypy3
>=v0.8.3 v2.0 v1.8, v1.11 v3.5, v3.6, pypy3
v0.8.x v2.0 v1.8, v1.10, v1.11 v2.7, v3.4, v3.5, v3.6 (only with Django 1.11)
>=v0.7.2 v2.0 v1.8, v1.9, v1.10 v2.7, v3.4, v3.5
v0.7.x v2.0 v1.8, v1.9 v2.7, v3.4, v3.5
v0.6.x v1.9, v1.10 v1.8, v1.9 v2.7, v3.4, v3.5
>=v0.5.2 v1.9 v1.7, v1.8 v2.7, v3.4
>=v0.4 v1.8 v1.7 v2.7, v3.4
<v0.4 v1.6 v1.4 v2.7

These are the unittests variants. See also: /pyproject.toml Maybe other versions are compatible, too.

Changelog

Links

| Github | https://github.com/jedie/django-reversion-compare | | Python Packages | https://pypi.org/project/django-reversion-compare/ |

Donation

django-reversion-compare's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-reversion-compare's Issues

Compare doesn't show changes to related reverse foreignkey relationships

When using weak relationships, I can't see a way to view changes to related child items.

For example, with the following models:

class CodeList(models.Model):
    name = models.CharField(max_length=100)

class Code(models.Model):
    value = models.PositiveIntegerField(max_length=100)
    meaning = models.CharField(max_length=100)
    codelist = models.ForeignKey(CodeList,related_name="codes")

Only Codelist items would be exposed through the admin interface, with Code items being managed through inline tables. While django-reversion tracks the changes in relation to Codelist, these are not visible in django-reversion-compare because the reverse relation isn't a field.

Fortunately, if this hasn't been done before, I've done some work to resolve this and will fork and and submit a pull request later in the week.

Bug if use custom generic fields

Traceback:
File " venv\lib\site-packages\django\core\handlers\base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File " venv\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File " venv\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  89.         response = view_func(request, *args, **kwargs)
File " venv\lib\site-packages\django\contrib\admin\sites.py" in inner
  202.             return view(request, *args, **kwargs)
File " venv\lib\site-packages\reversion_compare\admin.py" in compare_view
  633.         compare_data, has_unfollowed_fields = self.compare(obj, request, version1, version2)
File " venv\lib\site-packages\reversion_compare\admin.py" in compare
  582.             obj_compare = CompareObjects(field, field_name, obj, version1, version2, self.revision_manager)
File " venv\lib\site-packages\reversion_compare\admin.py" in __init__
  223.         self.compare_obj1 = CompareObject(field, field_name, obj, version1, self.has_int_pk, self.adapter)
File " venv\lib\site-packages\reversion_compare\admin.py" in __init__
  48.         self.value = version.field_dict[field_name]

Exception Type: KeyError at /admin/blog/blogpost/2/history/compare/
Exception Value: 'comments'

Bug is i use custom fields:
comments = CommentsField(verbose_name=_("Comments"))

https://github.com/stephenmcd/mezzanine/blob/master/mezzanine/blog/models.py#L21

Changes to ManyToManyField appear later in subsequent version

Thanks for this project! Super helpful.

After setting it up for my project and running a few test runs, I noticed that if there is a change in a ManyToManyField, it appears in the subsequent version (and not in that version).

For example:

If the model has 3 fields:

name = models.CharField(max_length=200)
section = models.CharField(max_length=200)
area = models.ManyToManyField(Area, blank=True, db_index=True)

And we make the edits in 4 iterations:

Version 1: original
Version 2: name changed
Version 3: name and area changed
Version 4: section changed

On comparing version 1 and 2, I see the name changed (expected)
On comparing version 2 and 3, I see the name changed (unexpected - since area was also changed)
On comparing version 3 and 4, I see the section and the area changed (unexpected - since area was actually changed in the previous revision)

This is happening with all ManyToManyFields.

Is this a known issue? (not sure if the issue is with django-reversion or django-reversion-compare)

Build wheel from 0.6.1 source fails

I was trying to generate a wheelhouse for my environment and noticed that building the 0.6.1 version from source fails as follows:

$ python --version
Python 2.7.6
$ pip --version
pip 8.1.1 from /usr/local/lib/python2.7/dist-packages (python 2.7)
$ pip wheel --wheel-dir=./wheelhouse/ django-reversion-compare==0.6.1 --no-binary :all:
Collecting django-reversion-compare==0.6.1
  Using cached django-reversion-compare-0.6.1.tar.gz
Collecting Django>=1.8 (from django-reversion-compare==0.6.1)
  Using cached Django-1.9.5.tar.gz
Collecting django-reversion>=1.9 (from django-reversion-compare==0.6.1)
  Using cached django-reversion-1.10.2.tar.gz
Building wheels for collected packages: django-reversion-compare, Django, django-reversion
  Running setup.py bdist_wheel for django-reversion-compare ... error
  Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-vnzHV6/django-reversion-compare/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" bdist_wheel -d /tmp/tmpcK5OmGpip-wheel-:
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-x86_64-2.7
  creating build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/helpers.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/mixins.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/views.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/reversion_api.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/__init__.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/models.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/compare.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/forms.py -> build/lib.linux-x86_64-2.7/reversion_compare
  copying reversion_compare/admin.py -> build/lib.linux-x86_64-2.7/reversion_compare
  creating build/lib.linux-x86_64-2.7/tests
  copying tests/manage.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_onetoone_field.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_factory_car_models.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_variant_model.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_settings.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_simple_model.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_custom_model.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/views.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/__init__.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/urls.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/models.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_person_pet_models.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_view.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/admin.py -> build/lib.linux-x86_64-2.7/tests
  copying tests/test_factory_car_reverse_models.py -> build/lib.linux-x86_64-2.7/tests
  creating build/lib.linux-x86_64-2.7/tests/management
  copying tests/management/__init__.py -> build/lib.linux-x86_64-2.7/tests/management
  creating build/lib.linux-x86_64-2.7/tests/test_utils
  copying tests/test_utils/test_data.py -> build/lib.linux-x86_64-2.7/tests/test_utils
  copying tests/test_utils/test_cases.py -> build/lib.linux-x86_64-2.7/tests/test_utils
  copying tests/test_utils/__init__.py -> build/lib.linux-x86_64-2.7/tests/test_utils
  creating build/lib.linux-x86_64-2.7/tests/management/commands
  copying tests/management/commands/__init__.py -> build/lib.linux-x86_64-2.7/tests/management/commands
  copying tests/management/commands/run_testserver.py -> build/lib.linux-x86_64-2.7/tests/management/commands
  running egg_info
  writing requirements to django_reversion_compare.egg-info/requires.txt
  writing django_reversion_compare.egg-info/PKG-INFO
  writing top-level names to django_reversion_compare.egg-info/top_level.txt
  writing dependency_links to django_reversion_compare.egg-info/dependency_links.txt
  warning: manifest_maker: standard file '-c' not found

  reading manifest file 'django_reversion_compare.egg-info/SOURCES.txt'
  reading manifest template 'MANIFEST.in'
  warning: no files found matching '*.css' under directory '*'
  warning: no files found matching '*.js' under directory '*'
  warning: no previously-included files matching '*.py[co]' found under directory '*'
  writing manifest file 'django_reversion_compare.egg-info/SOURCES.txt'
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/de
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/de/LC_MESSAGES
  copying reversion_compare/locale/de/LC_MESSAGES/django.mo -> build/lib.linux-x86_64-2.7/reversion_compare/locale/de/LC_MESSAGES
  copying reversion_compare/locale/de/LC_MESSAGES/django.po -> build/lib.linux-x86_64-2.7/reversion_compare/locale/de/LC_MESSAGES
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/el
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/el/LC_MESSAGES
  copying reversion_compare/locale/el/LC_MESSAGES/django.mo -> build/lib.linux-x86_64-2.7/reversion_compare/locale/el/LC_MESSAGES
  copying reversion_compare/locale/el/LC_MESSAGES/django.po -> build/lib.linux-x86_64-2.7/reversion_compare/locale/el/LC_MESSAGES
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/fr
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/fr/LC_MESSAGES
  copying reversion_compare/locale/fr/LC_MESSAGES/django.mo -> build/lib.linux-x86_64-2.7/reversion_compare/locale/fr/LC_MESSAGES
  copying reversion_compare/locale/fr/LC_MESSAGES/django.po -> build/lib.linux-x86_64-2.7/reversion_compare/locale/fr/LC_MESSAGES
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/nl
  creating build/lib.linux-x86_64-2.7/reversion_compare/locale/nl/LC_MESSAGES
  copying reversion_compare/locale/nl/LC_MESSAGES/django.mo -> build/lib.linux-x86_64-2.7/reversion_compare/locale/nl/LC_MESSAGES
  copying reversion_compare/locale/nl/LC_MESSAGES/django.po -> build/lib.linux-x86_64-2.7/reversion_compare/locale/nl/LC_MESSAGES
  creating build/lib.linux-x86_64-2.7/reversion_compare/templates
  creating build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/action_list_partial.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_BooleanField.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_DateTimeField.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_generic_add.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_generic_many_to_many.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_generic_remove.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_links_partial.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/compare_partial.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  copying reversion_compare/templates/reversion-compare/object_history.html -> build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare
  creating build/lib.linux-x86_64-2.7/tests/templates
  creating build/lib.linux-x86_64-2.7/tests/templates/tests
  copying tests/templates/tests/simplemodel_detail.html -> build/lib.linux-x86_64-2.7/tests/templates/tests
  installing to build/bdist.linux-x86_64/wheel
  running install
  running install_lib
  creating build/bdist.linux-x86_64
  creating build/bdist.linux-x86_64/wheel
  creating build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/helpers.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/mixins.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/views.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  creating build/bdist.linux-x86_64/wheel/reversion_compare/templates
  creating build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/action_list_partial.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_BooleanField.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/object_history.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_DateTimeField.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_partial.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_generic_add.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_generic_remove.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_generic_many_to_many.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/templates/reversion-compare/compare_links_partial.html -> build/bdist.linux-x86_64/wheel/reversion_compare/templates/reversion-compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/reversion_api.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/__init__.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/el
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/el/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/el/LC_MESSAGES/django.po -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/el/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/el/LC_MESSAGES/django.mo -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/el/LC_MESSAGES
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/nl
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/nl/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/nl/LC_MESSAGES/django.po -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/nl/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/nl/LC_MESSAGES/django.mo -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/nl/LC_MESSAGES
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/fr
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/fr/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/fr/LC_MESSAGES/django.po -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/fr/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/fr/LC_MESSAGES/django.mo -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/fr/LC_MESSAGES
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/de
  creating build/bdist.linux-x86_64/wheel/reversion_compare/locale/de/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/de/LC_MESSAGES/django.po -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/de/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/locale/de/LC_MESSAGES/django.mo -> build/bdist.linux-x86_64/wheel/reversion_compare/locale/de/LC_MESSAGES
  copying build/lib.linux-x86_64-2.7/reversion_compare/models.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/compare.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/forms.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  copying build/lib.linux-x86_64-2.7/reversion_compare/admin.py -> build/bdist.linux-x86_64/wheel/reversion_compare
  creating build/bdist.linux-x86_64/wheel/tests
  creating build/bdist.linux-x86_64/wheel/tests/management
  copying build/lib.linux-x86_64-2.7/tests/management/__init__.py -> build/bdist.linux-x86_64/wheel/tests/management
  creating build/bdist.linux-x86_64/wheel/tests/management/commands
  copying build/lib.linux-x86_64-2.7/tests/management/commands/__init__.py -> build/bdist.linux-x86_64/wheel/tests/management/commands
  copying build/lib.linux-x86_64-2.7/tests/management/commands/run_testserver.py -> build/bdist.linux-x86_64/wheel/tests/management/commands
  copying build/lib.linux-x86_64-2.7/tests/manage.py -> build/bdist.linux-x86_64/wheel/tests
  creating build/bdist.linux-x86_64/wheel/tests/test_utils
  copying build/lib.linux-x86_64-2.7/tests/test_utils/test_data.py -> build/bdist.linux-x86_64/wheel/tests/test_utils
  copying build/lib.linux-x86_64-2.7/tests/test_utils/test_cases.py -> build/bdist.linux-x86_64/wheel/tests/test_utils
  copying build/lib.linux-x86_64-2.7/tests/test_utils/__init__.py -> build/bdist.linux-x86_64/wheel/tests/test_utils
  copying build/lib.linux-x86_64-2.7/tests/test_onetoone_field.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_factory_car_models.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_variant_model.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_settings.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_simple_model.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_custom_model.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/views.py -> build/bdist.linux-x86_64/wheel/tests
  creating build/bdist.linux-x86_64/wheel/tests/templates
  creating build/bdist.linux-x86_64/wheel/tests/templates/tests
  copying build/lib.linux-x86_64-2.7/tests/templates/tests/simplemodel_detail.html -> build/bdist.linux-x86_64/wheel/tests/templates/tests
  copying build/lib.linux-x86_64-2.7/tests/__init__.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/urls.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/models.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_person_pet_models.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_view.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/admin.py -> build/bdist.linux-x86_64/wheel/tests
  copying build/lib.linux-x86_64-2.7/tests/test_factory_car_reverse_models.py -> build/bdist.linux-x86_64/wheel/tests
  running install_egg_info
  Copying django_reversion_compare.egg-info to build/bdist.linux-x86_64/wheel/django_reversion_compare-0.6.1-py2.7.egg-info
  running install_scripts
  error: [Errno 2] No such file or directory: 'LICENSE'

  ----------------------------------------
  Failed building wheel for django-reversion-compare
  Running setup.py clean for django-reversion-compare
  Running setup.py bdist_wheel for Django ... done
  Stored in directory: /home/user/wheelhouse
  Running setup.py bdist_wheel for django-reversion ... done
  Stored in directory: /home/user/wheelhouse
Successfully built Django django-reversion
Failed to build django-reversion-compare
ERROR: Failed to build one or more wheels

Key part is here:

  running install_scripts
  error: [Errno 2] No such file or directory: 'LICENSE'

Installing from the wheel published in pypi works as expected. Any hint on getting this to work without switching to installing it from binary?

Add history view/compare for non-admin views

One nice to have feature would be to have a CBV (probably a DetailView) that would display the list of versions to allow selecting the versions to compare and the differences between two versions. I don't really like giving access to /admin to non-technical users while the history of an object is something that is often needed by non-technical users (for auditing reasons).

From what I've seen, most of the functionality for the described feature is already there, however some refactory would be needed to extract duplicate functionality to common methods between the admin and non-admin views.

Because I need this feature for one of my projects I could implement it if you think that it could be a part of django-reversion-compare.

TIA

Not compatible with Django 1.10

_meta API has changed (migration instructions). Haven't looked through the code, so I don't know how extensive your usage of it is, but after enabling django-reversion-compare on 1.10 I get this:

Traceback:

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/django/contrib/admin/sites.py" in inner
  211.             return view(request, *args, **kwargs)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/reversion_compare/admin.py" in compare_view
  173.         compare_data, has_unfollowed_fields = self.compare(obj, version1, version2)

File "/home/hello/miniconda3/envs/redhair/lib/python3.5/site-packages/reversion_compare/mixins.py" in compare
  95.         for field_name in obj._meta.get_all_field_names():

Exception Type: AttributeError at /admin/scrape/listingdetail/160/history/compare/
Exception Value: 'Options' object has no attribute 'get_all_field_names'

Django 1.10 depreciation warning

RemovedInDjango110Warning: django.conf.urls.patterns() is deprecated and will be removed in Django 1.10. Update your urlpatterns to be a list of django.conf.urls.url() instances instead.
name='%s_%s_compare' % info),

reversion_compare\admin.py:95

Does not work with django-taggit

Django-reversion-compare seems to have a good deal of problems with django-taggit; perhaps it's due to django-taggit not being up-to-date enough with Django 1.4.5, but I tried both yedpodtrzitko's and shakirjames's and both exhibit the same issue.

Django 1.4.5 with a model as following:

class Argument(models.Model):
    tags = TaggableManager(through=TaggedTags)
    tags.rel.related_name = 'tags'

django-reversion-compare throws a KeyError at reversion_compare/admin.py:48:

self.value = version.field_dict[field_name] 

Changing this line to version.field_dict.get(field_name, None) makes it go down a rabbit-hole of issues with TaggableManager not providing get_internal_type which d-r-c makes use of frequently, eg:

# Line 81
assert self.field.get_internal_type() != "ManyToManyField" 
# Line 225
if self.field.get_internal_type() == "ManyToManyField":
# etc

Is the right solution to check in all places where get_internal_type is used to ensure the field hasattr(field, 'get_internal_type')?

Ignore relations that are not registered.

Certain models can have a lot of FK/M2M keys that are not worth registering (e.g. Employee model that has FKs to AttendanceLog which is a simple from_dt, to_dt). When we register Employee but not AttendanceLog, an error is raised:

reversion.errors.RegistrationError: <class 'human_resources.models.AttendanceLog'> has not been registered with django-reversion

when trying to use HistoryCompareDetailView. More precisely, this error happens here:
https://github.com/jedie/django-reversion-compare/blob/master/reversion_compare/compare.py#L205

Maybe it should be checked whether a child model is registered before trying to fetch its revisions?

using search_fields gives an error

@admin.register(School)  
class SchoolAdmin(CompareVersionAdmin):
    search_fields = ['name']

If I use search_fields like the one above, I get the error 'Cannot resolve keyword 'user' into field. Choices are...' This error does not come if I inherit from admin.ModelAdmin.

Fix README

The image attachment in the README file are not visible anymore...

revision comment when revision is created outside of admin

When non-admin users on my website save changes to an object, a comment is not automatically added to the revision in admin (the changes are observable in the comparison view for all revisions, and comments are generated automatically for changes which are made to objects using the admin).

Is that the intended behavior? Is there a setting or simple implementation that makes this possible which I have omitted?

Unable to compare followed reverse foreign relation fields that are on a non-abstract parent class

For example, given the models and register below:

class Association(Model):
    related_to = ForeignKey('Parent',related_name='associations')

class Parent(Model):
    text = TextField(null=True)

class Child(Parent):
    more_text = TextField(null=True)

reversion.revisions.register(Child, follow=['parent_ptr','associations'])

Both the parent and child instances will be stored in the relation, but due to how django serialisers work for multi-table inheritance the associations field will only be available on the Parent reversion, not the Child reversion. I've made a PR that addresses that will be added soon.

Adding a new ManyToMany relationship causes exception

It seems that adding a new ManyToMany relationship, and then comparing an object seems to cause it to break.

reversion_compare/admin.py:50 sets "Field Didn't exist!" in this case, as the old reversion of the model doesn't have the value, and then reversion_compare/admin.py:124 blows up on that value.

I would propose putting a try/except and return the new list of ids in this case. I'm happy to do a pull-request if you agree this is appropriate.

Thanks.

Incorrect requires.txt in official pypi distribution of 0.5.2

Specifically, release 0.5.2 of django-reversion-compare lists Django 1.8 as supported.

Looking in the setup.py in the repo, it lists the supported Django versions as >=1.7,<1.9

However, installing django-reversion-compare from the official pypi repository, the egg comes down with the requires.txt listing Django>=1.7,<1.8.

Installing into a project that uses Django 1.8 (I'm currently on 1.8.2, moving to 1.8.3) forcibly downgrades me to Django 1.7.9.

The compare view is extremely slow

I am having a problem in my setup, all my compare views are extremely slow (I'm getting bad gateway from my reverse proxy in production), even when there is a very little change. I see a little bit of load on the database, and a very high CPU usage on the python process when showing the page.

The pages takes around 45s to show on my development laptop (With a copy of the production database).

select count(*) from reversion_revision;
29668

select count(*) from reversion_version;
66641

Here are my versions :

django==1.11.5
django-reversion==2.0.10
django-reversion-compare==0.8.0

Using MySQL as backend.

What could be the issue ? Is this an expected behaviour ?

PS: Awesome project :P

View changes of related objects (models.ForeignKey)

I have Enterprise model and related ContactPerson and Phone models:

@reversion.register()
class Enterprise(models.Model):
    # ...

@reversion.register()
class ContactPerson(models.Model):
    enterprise = models.ForeignKey(Enterprise, on_delete=models.CASCADE)
    # Other fields

@reversion.register()
class Phone(models.Model):
    enterprise = models.ForeignKey(Enterprise, on_delete=models.CASCADE)
    # Other fields

In both backend and frontend, these related models are edited together with Enterprise using formsets. For example in admin I define inlines like this:

class EnterpriseAdmin(CompareVersionAdmin):
    inlines = [ContactPersonInline, PhoneInline]

Changes of related models are tracked with main model (for_concrete_model=True and it's True by default, I haven't changed it).

It would be great if in detail compare page I can see changes of each of these related models (including all fields) together with main model.

I see that extension has some support for viewing m2m relations changes, but can't find it for relations with models.ForeignKey.

Now the changes to related models are detectable only from change message and details - by manual comparing (opening one version in one browser tab, second one - in another and manually see what's changed in the forms).

ForeignKey relation

Hi,

I was trying out your app and noticed something weird. Why is a normal ForeignKey (that we are not registering in reversion) showing up on the diff panel? Even if it's empty it always shows 'add: None'. That does not make any sense since this class has the information about that ForeignKey (throw a relational ID). Then I started watching the code and, if I saw correctly, these fields are treated as reversed relations, which they are not.

Support django 1.11

Does it support django >= 1.11? Right now if you want to install this package, django will be downgrade to 1.10.7

Inclusion of TabularInline when comparing.

I would like to ask if it is possible to include the TabularInlines when comparing? If yes, may I know if there's an example for it?

No. But you will see ForeignKey...

django-reversion==2.0.0

Since django-reversion major version has been released, there are plenty of breaking changes.

We should go over changelog and fix all of them.

And release new version (1.0.0, or even 2.0.0 to be in touch with main reversion package).

Comparing booleans is awkward

When comparing a boolean field that goes from True and False, sometimes it gives results like that below:

image

I'm having a look at how this could be improved.

invalid literal for int() with base 10: 'F'

I was trying to compare two versions and got an error:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:10801/uk/admin/blog/post/4/history/compare/?version_id2=2&version_id1=1

Django Version: 1.8.3
Python Version: 3.4.0
Installed Applications:
('djangocms_admin_style',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'cmsplugin_cascade',
 'cmsplugin_cascade.extra_fields',
 'cmsplugin_cascade.sharable',
 'cms',
 'treebeard',
 'menus',
 'sekizai',
 'bootstrap3',
 'solo',
 'easy_thumbnails',
 'filer',
 'modeltranslation',
 'disqus',
 'django_select2',
 'easy_select2',
 'taggit',
 'mptt',
 'djangocms_inherit',
 'djangocms_picture',
 'djangocms_file',
 'djangocms_link',
 'djangocms_text_ckeditor',
 'blog',
 'settings',
 'reversion',
 'reversion_compare')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'cms.middleware.user.CurrentUserMiddleware',
 'cms.middleware.page.CurrentPageMiddleware',
 'cms.middleware.toolbar.ToolbarMiddleware',
 'cms.middleware.language.LanguageCookieMiddleware')


Traceback:
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/django/contrib/admin/sites.py" in inner
  233.             return view(request, *args, **kwargs)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in compare_view
  721.         compare_data, has_unfollowed_fields = self.compare(obj, version1, version2)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in compare
  676.             if not obj_compare.changed():
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in changed
  268.             info = self.get_m2m_change_info()
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in get_m2m_change_info
  324.         m2m_data1, m2m_data2 = self.get_many_to_many()
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in get_many_to_many
  301.         m2m_data1, m2m_data2 = self._get_both_results("get_many_to_many")
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in _get_both_results
  289.         result1 = self._get_result(self.compare_obj1, func_name)
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in _get_result
  285.         result = func()
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in get_many_to_many
  136.             ids = [int(v) for v in self.value]  # is: version.field_dict[field.name]
File "/home/blog_linevich_net/.env/lib/python3.4/site-packages/reversion_compare/admin.py" in <listcomp>
  136.             ids = [int(v) for v in self.value]  # is: version.field_dict[field.name]

Exception Type: ValueError at /uk/admin/blog/post/4/history/compare/
Exception Value: invalid literal for int() with base 10: 'F'

Django 1.8 Error - AttributeError: 'Options' object has no attribute 'module_name'

Testing against the new Django 1.8 shows an error:

  File "/home/travis/virtualenv/python2.7.9/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 275, in get_urls
    url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
  File "/home/travis/virtualenv/python2.7.9/lib/python2.7/site-packages/django/contrib/admin/options.py", line 631, in urls
    return self.get_urls()
  File "/home/travis/virtualenv/python2.7.9/src/django-reversion-compare/reversion_compare/admin.py", line 501, in get_urls
    info = opts.app_label, opts.module_name,
AttributeError: 'Options' object has no attribute 'module_name'

There might be more worth investigating. Would a Django 1.8 update justify a new point release on PIP?

Reverse test show incorrect field

I was doing some tests/upgrades for django 1.8 while trying to fix #33 and noticed a bug only under Django 1.7.
The list of changes for reverse fields incorrectly includes a "deletion" for the item that was added in.

Under Django 1.7:

   [DEL: - motor-car four from factory one supplier(s): :DEL] ^*
   [DEL: - motor-car three from factory one supplier(s): :DEL] → Deleted
   [INS: + motor-car four from factory one supplier(s): :INS]
   motor-car one from factory one supplier(s):

Edit comment:

     version 2: discontinued car-three, add car-four

Compared to the correct result under Django 1.8:

   [DEL: - motor-car three from factory one supplier(s): :DEL] → Deleted
   [INS: + motor-car four from factory one supplier(s): :INS]
   motor-car one from factory one supplier(s):

Edit comment:

     version 2: discontinued car-three, add car-four

"Previous" and "Next" buttons on compare.html are non-functional

It's clear from the href="#TODO" that this is a known issue - but as a non-functional part of the UI it is a potential source of confusion for users.

Possible fixes:

  1. Implement the previous/next browsing functionality
  2. Remove buttons from UI (to return later if the feature is implemented)

Failure when inspecting reverse OneToOneFields

class User(Model):
    meta = OneToOneField(UserMetadata, related_name='user')

class UserMetadata(Model):
    pass

When I try to compare UserMetadata instances, I get the following error:

Exception Type: AttributeError
Exception Value:    
'User' object has no attribute 'all'

It seems that it thinks it is a related manager instead of object.

Can not use django-reversion-compare

When I add 'reversion-compare' into INSTALLED_APPS then I am getting this following error..

/home/shetu/Envs/test/bin/python /home/shetu/workspace/personal/test/manage.py runserver 8000
Unhandled exception in thread started by <function wrapper at 0x7fe5028245f0>
Traceback (most recent call last):
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper fn(*args, **kwargs)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 109, in inner_run autoreload.raise_last_exception()
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 249, in raise_last_exception six.reraise(*_exception)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper fn(*args, **kwargs)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/__init__.py", line 18, in setup apps.populate(settings.INSTALLED_APPS)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/apps/registry.py", line 115, in populate app_config.ready()
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/contrib/admin/apps.py", line 22, in ready self.module.autodiscover()
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/contrib/admin/__init__.py", line 26, in autodiscover autodiscover_modules('admin', register_to=site)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/django/utils/module_loading.py", line 50, in autodiscover_modules import_module('%s.%s' % (app_config.name, module_to_search))
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module __import__(name)
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/reversion_compare/admin.py", line 39, in <module> from reversion_compare.mixins import CompareMixin, CompareMethodsMixin
File "/home/shetu/Envs/test/local/lib/python2.7/site-packages/reversion_compare/mixins.py", line 15, in <module> from reversion.revisions import default_revision_manager
ImportError: cannot import name default_revision_manager

@property diff

Is there any way I can tweak this library to do a comparison over a property of my model?
This property gathers information from relationships and returns json, it would be awesome to make this work but I didn't find anything in the documentation about custom comparators that can be added to a model in the admin panel.

Create a history outside the admin page

If I following this HistoryCompareDetailView, I only can show the revisions if I changed the object at admin page default django. In my case, I need to create a history whenever I update that object ouside the admin.. Possible me to do this?

update

recommended way to exclude fields from comparison?

When I try to exclude a ManyToOne relation, there is an exception when I try to compare two versions of the same model, because the exclude is unaccounted for during the comparison process.

Here is a stack trace. The line numbers are slightly off because I inserted some debug code:

Environment:


Request Method: GET
Request URL: http://localhost:8080/admin/klmno/page/701/history/compare/?version_id2=7680&version_id1=7678

Django Version: 1.10.3
Python Version: 2.7.10
Installed Applications:
('grappelli',
 'nested_admin',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.postgres',
 'social.apps.django_app.default',
 'raven.contrib.django.raven_compat',
 'concurrency',
 'reversion',
 'reversion_compare',
 'django_js_reverse',
 'django_extensions',
 'klmno',
 'sherpa_auth')
Installed Middleware:
(u'raven.contrib.django.middleware.SentryMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'klmno.middleware.DebugHeadersMiddleware',
 'klmno.middleware.RequestCacheMiddleware',
 'concurrency.middleware.ConcurrencyMiddleware',
 'threadlocals.middleware.ThreadLocalMiddleware',
 'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
 'sherpa_auth.middleware.AuthEnforcementMiddleware')



Traceback:

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
  211.             return view(request, *args, **kwargs)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/admin.py" in compare_view
  174.         compare_data, has_unfollowed_fields = self.compare(obj, version1, version2)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/mixins.py" in compare
  144.             if not obj_compare.changed():

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in changed
  282.             info = self.get_m2o_change_info()

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in get_m2o_change_info
  311.         m2o_data1, m2o_data2 = self.get_reverse_foreign_key()

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in get_reverse_foreign_key
  305.         return self.compare_obj1.get_reverse_foreign_key(), self.compare_obj2.get_reverse_foreign_key()

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in get_reverse_foreign_key
  144.         return self.get_many_to_something(ids, related_model, is_reverse=True)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in get_many_to_something
  190.                 for o in missing_objects_dict.values()

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion_compare/compare.py" in <dictcomp>
  191.                 for ver in Version.objects.get_for_object(o)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/models.py" in get_for_object
  118.         return self.get_for_object_reference(obj.__class__, obj.pk, model_db=model_db)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/models.py" in get_for_object_reference
  113.         return self.get_for_model(model, model_db=model_db).filter(

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/models.py" in get_for_model
  106.         content_type = _get_content_type(model, self.db)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/revisions.py" in _get_content_type
  402.     version_options = _get_options(model)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/revisions.py" in _get_options
  388.     _assert_registered(model)

File "/Users/Hahn/.virtualenvs/sherpa/lib/python2.7/site-packages/reversion/revisions.py" in _assert_registered
  383.             model=model,

Exception Type: RegistrationError at /admin/klmno/page/701/history/compare/
Exception Value: <class 'klmno.models.PageUsageLog'> has not been registered with django-reversion

The model being compared has the related_name in the exclude list.

For now, I'm using compare_exclude to avoid the issue. However, this is not documented, so I'm not sure if this solution will work when I upgrade this library.

Is this the recommended solution?

Either way, my assumption was that exclude would propagate from registration to comparison, as one would never be able to compare fields that were never included in the first place. But maybe there are edge cases I'm not considering.

Does django reversion support with markdown syntax?

markdown

If I following

{% for field_diff in compare_data %}
    {{ field_diff }}

The html output is;

{'diff': '<span>Dynamically evolve tactical e-business whereas client-focused technology. Monotonectally evolve top-line strategic theme areas after optimal technology. Authoritatively empower fully researched results for backend synergy. Credibly maintain ethical imperatives without ethical scenarios. Intrinsicly incubate bricks-and-clicks infrastructures without intuitive partnerships\r</br>\r</br></span><del style="background:#ffe6e6;">Interactively implement exceptional human capital after team driven e-services. Energistically reinvent orthogonal meta-services before empowered strategic</del><ins style="background:#e6ffe6;">```python\r</br>class QuestionEdit(LoginRequiredMixin, RevisionMixin, FormView):\r</br> </ins><span> t</span><del style="background:#ffe6e6;">h</del><span>em</span><del style="background:#ffe6e6;">e areas. Appropriately orchestrate transparent experiences without scalable meta-services. Efficiently empower seamless best practices rather than extensive niche markets. Rapidiously transition future-proof manufactured products and empowered communities.</del><ins style="background:#e6ffe6;">plate_name = \'app_faq/question_edit.html\'\r</br> form_class = QuestionForm\r</br> model = Question\r</br>\r</br> def post(self, request, **kwargs):\r</br> reversion_set_comment("foo bar")\r</br> return super(QuestionEdit, self).post(request, **kwargs)\r</br>```</ins>', 'is_related': False, 'follow': None, 'field': <django.db.models.fields.TextField: description>}

The {{ field_diff.diff }} is converted as html. How I can handle the markdown syntax?


https://github.com/etianen/django-reversion/wiki/_history

or maybe like this;

two

DoesNotExist usind django comments model

model inherit from django comments model, get this error:

File "/home/jens/PyLucid_env/src/django-reversion-compare/reversion_compare/admin.py" in get_related
  101.             related = getattr(obj, field_name)
File "/home/jens/PyLucid_env/src/django/django/db/models/fields/related.py" in __get__
  343.                 raise self.field.rel.to.DoesNotExist

Exception Type: DoesNotExist at /admin/pylucid_comments/pylucidcomment/2/history/compare/
Exception Value: 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.