Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add Support for Django 1.11 and add Python 3 support. #27

Open
wants to merge 64 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
af1a3b8
adding ability to revert a change to a model
binarymatt Sep 23, 2013
95f6de8
adding revert action for delete and change operations
binarymatt Sep 23, 2013
a915372
Merge remote-tracking branch 'upstream/master'
binarymatt Oct 7, 2013
f8b472f
When loading fixtures, do not trigger audits.
Oct 22, 2013
a3c784b
Merge pull request #1 from briandailey/feature/accommodate-fixtures
briandailey Oct 23, 2013
4eb06ae
Bumping version number.
Oct 23, 2013
46566eb
Increased Auditchange old_value and new_value to textfield
egdelwonk Nov 1, 2013
bca746d
Merge pull request #2 from egdelwonk/increase_auditchange_values
briandailey Nov 1, 2013
f432e8d
Changing version, contributors.
briandailey Mar 25, 2014
c92d47c
Merge pull request #3 from briandailey/master
briandailey Mar 25, 2014
62567ed
adding ability to revert a change to a model
binarymatt Sep 23, 2013
fcf4054
adding revert action for delete and change operations
binarymatt Sep 23, 2013
6c9d328
Back-merging latest.
Sep 18, 2014
51e1817
Back merging from stratasan fork.
Sep 18, 2014
8f8f4df
Merge pull request #4 from briandailey/master
briandailey Sep 18, 2014
66ecb5e
Adding build status badge.
Sep 18, 2014
167428f
t push Merge branch 'master' of github.com:stratasan/django-simple-audit
Sep 18, 2014
e3d26b5
use rst format.
Sep 18, 2014
b804c1b
https
Sep 18, 2014
3b7fc83
Back-merging upstream.
Nov 3, 2015
af36081
Remove maxlength on integer field.
Nov 3, 2015
37751f1
IPAddressField has been deprecated. Support for it (except in histori…
Nov 3, 2015
7aa18f0
Add migrations
sburns Feb 26, 2016
9b99cf7
Remove import in __init__
sburns Feb 29, 2016
a4a868b
Merge pull request #5 from briandailey/master
sburns Mar 1, 2016
3f5ca38
Update README and bump version
sburns Mar 1, 2016
294e8c2
Merge remote-tracking branch 'stratasan/master' into fix-warnings
sburns Mar 1, 2016
79ebf08
Merge pull request #6 from sburns/fix-warnings
sburns Mar 1, 2016
b6f81ca
Fix bad merge
sburns Mar 1, 2016
4180ce0
Merge pull request #7 from sburns/fix-warnings
sburns Mar 1, 2016
0de4123
Fix GenericForeignKey import
sburns Mar 1, 2016
cf49cab
Ignore vim swp files
sburns Mar 1, 2016
3e51c80
Fix _Meta API usage
sburns Mar 1, 2016
041d05d
Use Django 1.9 in testproject
sburns Mar 1, 2016
97c1000
Register simple_audit in simple_app.apps
sburns Mar 1, 2016
ba39f8b
Add travis
sburns Mar 1, 2016
68b41c6
attempting to trigger travis
sburns Mar 1, 2016
a109b52
Remove implicit import
sburns Mar 1, 2016
463f0d2
Fix py3 exception syntax
sburns Mar 1, 2016
3031df1
Only test py2.7 for now'
sburns Mar 1, 2016
4266d2d
Merge pull request #8 from sburns/fix-tests
sburns Mar 2, 2016
2f3d4f0
Update README
Chris-Graffagnino Dec 28, 2016
9435ffc
Remove patterns func call for Django 1.10 compatibility
Chris-Graffagnino Dec 28, 2016
04793f2
Merge pull request #9 from Chris-Graffagnino/update1.10
briandailey Feb 2, 2017
a3f0222
Change how _get_all_field_names is called
Chris-Graffagnino Feb 11, 2017
293f827
Simplify implementation for get_field_names
Chris-Graffagnino Feb 17, 2017
88e4698
Merge pull request #10 from Chris-Graffagnino/get-field-names
briandailey Feb 21, 2017
2dbaed9
Update setup.py
Chris-Graffagnino Feb 22, 2017
8ad3fbc
Merge pull request #11 from Chris-Graffagnino/patch-1
sburns Feb 24, 2017
57fd47a
Remove deprecated patterns function
WTFox Jan 22, 2018
6cb2980
Add support for python 2/3 strings
WTFox Jan 22, 2018
2e7e5a6
Cast dict.keys()s to a list
WTFox Jan 22, 2018
a01730b
Add a utility method to maintain consistent ordering when comparing.
WTFox Jan 22, 2018
8ece1d7
Remove redundant quotes
WTFox Jan 22, 2018
c8ae971
Update project meta
WTFox Jan 22, 2018
2782e06
Update travis-ci to test against py3
WTFox Jan 22, 2018
4aa211b
Remove 3.3 test environment
WTFox Jan 22, 2018
542fc71
Update CI and README
WTFox Jan 22, 2018
cbe7995
Merge remote-tracking branch 'upstream/master' into support-django1.1…
WTFox Jan 23, 2018
1514c44
Verify that values are quoted consistently
WTFox Jan 29, 2018
2845ec1
Correct backwards compatibility
WTFox Jan 29, 2018
3ce6608
More six compatibility
WTFox Jan 29, 2018
6e731b0
Use six.string_type
WTFox Jan 29, 2018
a45f0e6
Merge branch 'support-django1.11-python2or3' into upstream-support-dj…
WTFox Jan 30, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ build
dist
*.egg-info
*.orig
.*.swp
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: python
python:
- "2.7"
- "3.6"
# command to install dependencies
install: "pip install -r testproject/requirements.txt"
# command to run tests
script: make test
6 changes: 6 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ Contributors:
* Silvano Buback
* Gustavo Soares Souza
* Marcus Bergo
* Brian Dailey
* Matt George
* Will Golden
* Scott Burns
* Chris Graffagnino
* Anthony Fox
* Mauro Murari
14 changes: 12 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. image:: https://drone.io/github.com/stratasan/django-simple-audit/status.png

****************************************
django simple audit
****************************************
Expand Down Expand Up @@ -73,7 +75,7 @@ to audit a model you need import `simple_audit` and then register the model to b
return self.name


simple_audit.register(Message, Owner, VirtualMachine)
simple_audit.signal.register(Message, Owner, VirtualMachine)

Advanced Usage (without httprequest or our middleware)
--------------------------------------------------------
Expand Down Expand Up @@ -110,8 +112,9 @@ You need to have at least one cache backend set in your django settings, otherwi
Dependencies
============

* Django >= 1.4.x
* Django >= 1.8.x
* django.contrib.contenttypes installed in INSTALLED_APPS
* Supports Python >= 2.7 and Python3 >= 3.6


TODO
Expand All @@ -120,6 +123,13 @@ TODO

CHANGELOG
=========
* 0.4
* Update with compatibility for Django 1.11 and Python 3
* 0.3
* Update with compatibility for Django 1.10
* 0.2
* Update with compatibility for Django 1.9
* Add Migrations
* 0.1.22
* Fixing admin display Current Content when audited model was deleted ( thanks otherpirate )
* 0.1.21
Expand Down
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
STATUS_BETA = 'Development Status :: 4 - Beta'
STATUS_ALPHA = 'Development Status :: 3 - Alpha'

version = '0.1.22'
version = '0.2.1'
README = os.path.join(os.path.dirname(__file__), 'README.rst')
long_description = open(README).read()
setup(
Expand All @@ -21,6 +21,8 @@
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Utilities'],
keywords='revisions versioning history audit',
Expand Down
1 change: 0 additions & 1 deletion simple_audit/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from .signal import register
24 changes: 24 additions & 0 deletions simple_audit/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from django.utils.translation import ugettext_lazy as _
from django.utils.html import escape
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.conf.urls import url
from .models import Audit
from .signal import MODEL_LIST

Expand Down Expand Up @@ -42,6 +44,28 @@ class AuditAdmin(admin.ModelAdmin):
list_display = ("format_date", "audit_content", "operation", "audit_user", "audit_description", )
list_filter = ("operation", ContentTypeListFilter,)

def get_urls(self):
urls = super(AuditAdmin, self).get_urls()
my_urls = [
url(r'^revert/(?P<audit_id>\d+)/$', self.admin_site.admin_view(self.revert_change), name='simple_audit_audit_revert')
]
return my_urls + urls

def revert_change(self, request, audit_id):
audit = Audit.objects.get(pk=audit_id)
if audit.operation == Audit.CHANGE:
audit_obj = audit.content_object
for change in audit.field_changes.all():
setattr(audit_obj, change.field, change.old_value)
audit_obj.save(force_insert=False)
elif audit.operation == Audit.DELETE:
audit_obj = audit.content_type.model_class()(pk=audit.object_id)
for change in audit.field_changes.all():
setattr(audit_obj, change.field, change.new_value)
audit_obj.save(force_insert=True)

return redirect('admin:simple_audit_audit_changelist')

def format_date(self, obj):
return obj.date.strftime('%d/%m/%Y %H:%M')
format_date.short_description = _("Date")
Expand Down
19 changes: 11 additions & 8 deletions simple_audit/m2m_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ def ValuesQuerySetToDict(vqs):


def get_m2m_fields_for(instance=None):
"""gets m2mfields for instance"""
return instance._meta._many_to_many()
"""gets m2mfields for instance

instance._meta._many_to_many was deprecated, this follows
https://docs.djangoproject.com/en/1.9/ref/models/meta/#migrating-from-the-old-api
for migrating to the new API. This is similar to get_m2m_with_model
except only includes field in the list and not their models. """
return [f for f in instance._meta.get_fields()
if f.many_to_many and not f.auto_created]


def get_m2m_values_for(instance=None):
Expand Down Expand Up @@ -83,18 +89,15 @@ def m2m_clean_unchanged_fields(dict_diff):
returns a list of dicts with only the changes
"""
dict_list = []
for key in dict_diff.keys():
for key in list(dict_diff.keys()):
new_dict = {}
dict_ = dict_diff.get(key)

for value in dict_.keys():
for value in list(dict_.keys()):
compound_key = "%s.%s" % (key, value)
if dict_[value][0] == dict_[value][1]:
del dict_[value]
else:
if not dict_[value][0] == dict_[value][1]:
new_dict[compound_key] = dict_[value]

del dict_diff[key]
if new_dict:
dict_list.append(new_dict)

Expand Down
73 changes: 73 additions & 0 deletions simple_audit/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Audit',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('date', models.DateTimeField(auto_now_add=True, verbose_name='Date')),
('operation', models.PositiveIntegerField(max_length=255, verbose_name='Operation', choices=[(0, 'add'), (1, 'change'), (2, 'delete')])),
('object_id', models.PositiveIntegerField()),
('description', models.TextField()),
('obj_description', models.CharField(db_index=True, max_length=100, null=True, blank=True)),
],
options={
'db_table': 'audit',
'verbose_name': 'Audit',
'verbose_name_plural': 'Audits',
},
),
migrations.CreateModel(
name='AuditChange',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('field', models.CharField(max_length=255)),
('old_value', models.TextField(null=True, blank=True)),
('new_value', models.TextField(null=True, blank=True)),
('audit', models.ForeignKey(related_name='field_changes', to='simple_audit.Audit')),
],
options={
'db_table': 'audit_change',
'verbose_name': 'Audit',
'verbose_name_plural': 'Audits',
},
),
migrations.CreateModel(
name='AuditRequest',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('request_id', models.CharField(max_length=255)),
('ip', models.IPAddressField()),
('path', models.CharField(max_length=1024)),
('date', models.DateTimeField(auto_now_add=True, verbose_name='Date')),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
options={
'db_table': 'audit_request',
'verbose_name': 'Audit',
'verbose_name_plural': 'Audits',
},
),
migrations.AddField(
model_name='audit',
name='audit_request',
field=models.ForeignKey(to='simple_audit.AuditRequest', null=True),
),
migrations.AddField(
model_name='audit',
name='content_type',
field=models.ForeignKey(to='contenttypes.ContentType'),
),
]
24 changes: 24 additions & 0 deletions simple_audit/migrations/0002_auto_fix_field_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('simple_audit', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='audit',
name='operation',
field=models.PositiveIntegerField(verbose_name='Operation', choices=[(0, 'add'), (1, 'change'), (2, 'delete')]),
),
migrations.AlterField(
model_name='auditrequest',
name='ip',
field=models.GenericIPAddressField(),
),
]
Empty file.
17 changes: 9 additions & 8 deletions simple_audit/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from django.db import models
from .managers import AuditManager
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils.translation import ugettext_lazy as _

from django.utils.encoding import python_2_unicode_compatible

LOG = logging.getLogger(__name__)

Expand All @@ -28,6 +28,7 @@ def title(self):
__deepcopy__ = lambda self, memodict: self


@python_2_unicode_compatible
class Audit(models.Model):
ADD = 0
CHANGE = 1
Expand All @@ -38,10 +39,10 @@ class Audit(models.Model):
(DELETE, _('delete'))
)
date = models.DateTimeField(auto_now_add=True, verbose_name=_("Date"))
operation = models.PositiveIntegerField(max_length=255, choices=OPERATION_CHOICES, verbose_name=_('Operation'))
operation = models.PositiveIntegerField(choices=OPERATION_CHOICES, verbose_name=_('Operation'))
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField(db_index=True)
content_object = generic.GenericForeignKey('content_type', 'object_id')
content_object = GenericForeignKey('content_type', 'object_id')
audit_request = models.ForeignKey("AuditRequest", null=True)
description = models.TextField()
obj_description = models.CharField(max_length=100, db_index=True, null=True, blank=True)
Expand All @@ -64,13 +65,13 @@ def register(audit_obj, description, operation=None):
audit.operation = Audit.CHANGE if operation is None else operation
audit.content_object = audit_obj
audit.description = description
audit.obj_description = (audit_obj and unicode(audit_obj) and '')[:100]
audit.obj_description = (audit_obj and str(audit_obj) and '')[:100]
audit.audit_request = AuditRequest.current_request(True)
audit.save()
return audit

def __unicode__(self):
return u"%s" % (self.operation)
def __str__(self):
return "%s" % (self.operation)


class AuditChange(models.Model):
Expand All @@ -91,7 +92,7 @@ class AuditRequest(models.Model):
THREAD_LOCAL = threading.local()

request_id = models.CharField(max_length=255)
ip = models.IPAddressField()
ip = models.GenericIPAddressField()
path = models.CharField(max_length=1024)
date = models.DateTimeField(auto_now_add=True, verbose_name=_("Date"))
user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'))
Expand Down
Loading