Skip to content

Commit

Permalink
Added possibility for creating GenericRelations with UUID Fields
Browse files Browse the repository at this point in the history
  • Loading branch information
anx-ckreuzberger committed Jun 30, 2017
1 parent c6530ca commit 258729a
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 7 deletions.
97 changes: 97 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,100 @@ Known problems
Do **not** use any of the following names in your models: ``created_at``, ``created_by``, ``change_sets``,
``last_modified_by``, ``last_modified_at``, ``changed_data``


Generic Relations
-----------------

It is possible to use Django Changeset with Djangos ``GenericRelation`` like this (tested with Django 1.11):

.. code-block:: python
class MyModel(models.Model, RevisionModelMixin):
...
changesets = GenericRelation(
ChangeSet,
content_type_field='object_type',
object_id_field='object_uuid'
)
This allows the Django ORM to use queries on changeset (e.g., on the changeset type INSERT):

.. code-block:: python
MyModel.objects.filter(changesets__changeset_type='I')
Generic Relations with UUID
---------------------------

The query from above does not work in Postgres when using the built-in ``UUID`` datatype, e.g.:

.. code-block:: python
class MyModel(models.Model, RevisionModelMixin):
my_pk = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
...
changesets = GenericRelation(
ChangeSet,
content_type_field='object_type',
object_id_field='object_uuid'
)
This is due to the fact that the ``ChangeSet`` model uses a ``CharField(max_length=...)`` for the ``object_uuid``.
It is possible to change this behaviour by using ``DJANGO_CHANGESET_PK_TYPE = "UUID"`` in your Django settings file.
This will convert swap out the basic ``object_uuid`` field from:

.. code-block:: python
object_uuid = models.CharField(
verbose_name=_(u"Object UUID"),
max_length=255,
editable=False,
)
to this:

.. code-block:: python
object_uuid = models.UUIDField(
verbose_name=_(u"Object UUID"),
editable=False,
)
This obviously **requires** a migration! Do **not** run the ``makemigrations`` command to do this. Instead, add a
migration file manually to **your application** (e.g., ``your_app``), which will look something like this:

.. code-block:: python
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-06-30 08:22
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_changeset', '0002_add_index_changesettype'),
('your_app', '0815_your_last_migration')
]
operations = [
migrations.AlterField(
model_name='changeset',
name='object_uuid',
field=models.UUIDField(editable=False, verbose_name='Object UUID'),
),
]
def __init__(self, name, app_label):
super(Migration, self).__init__(name, 'django_changeset')
32 changes: 26 additions & 6 deletions django_changeset/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text

Expand All @@ -13,7 +15,7 @@
logger = logging.getLogger(__name__)


class ChangeSet(models.Model):
class AbstractChangeSet(models.Model):
""" Basic changeset/revision model which contains the ``user`` that modified the object ``object_type`` """

# choices for changeset type (insert, update, delete)
Expand Down Expand Up @@ -65,16 +67,17 @@ class ChangeSet(models.Model):
null=False,
)

object_uuid = models.CharField(
verbose_name=_(u"Object UUID"),
max_length=255,
editable=False,
)
# object_uuid = models.CharField(
# verbose_name=_(u"Object UUID"),
# max_length=255,
# editable=False,
# )

class Meta:
app_label = 'django_changeset'
get_latest_by = 'date'
ordering = ['-date', ]
abstract = True

def __unicode__(self):
return _(u"%(changeset_type)s on %(app_label)s.%(model)s %(uuid)s at date %(date)s by %(user)s") % {
Expand All @@ -89,6 +92,23 @@ def __unicode__(self):
def __str__(self):
return self.__unicode__()

from django.conf import settings


if hasattr(settings, "DJANGO_CHANGESET_PK_TYPE") and settings.DJANGO_CHANGESET_PK_TYPE == 'UUID':
class ChangeSet(AbstractChangeSet):
object_uuid = models.UUIDField(
verbose_name=_(u"Object UUID"),
editable=False,
)
else:
class ChangeSet(AbstractChangeSet):
object_uuid = models.CharField(
verbose_name=_(u"Object UUID"),
max_length=255,
editable=False,
)


class ChangeRecord(models.Model):
""" A change_record represents detailed change information, like which field was changed and what the old aswell as
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name='django-changeset',
version='0.6.2',
version='0.7.0',
packages=find_packages(),
include_package_data=True,
license='BSD License',
Expand Down

0 comments on commit 258729a

Please sign in to comment.