incuna / django-orderable

Add manual sort order to Django objects via an abstract base class and admin classes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`unique_together` doesn't work seamlessly

meshy opened this issue · comments

If your sort_order field is unique_together with something, you need to add:

def validate_unique(self, exclude=None):
    f = 'sort_order'
    exclude = [f] if not exclude and f not in exclude else exclude + [f]
    return super(MyModel, self).validate_unique(exclude)

To your model.

Rewritten as a logical if statement…

if not exclude and 'sort_order' not in exclude:
    exclude = ['sort_order']
else:
    exclude = exclude + ['sort_order' ]

but, if exclude is None then how could sort_order be in exclude?

Logic fail. Should be:

def validate_unique(self, exclude=None):
    if exclude is None:
        exclude = ['sort_order']
    elif 'sort_order' not in exclude:
        exclude = exclude + ['sort_order']
    return super(MyModel, self).validate_unique(exclude=exclude)

Can this not be added to the Orderable object then?

I am unsure of the implications of ignoring validation on this, especially as it only applies when sort_order is unique (which it is not, by default).

Guess we just mention it in the README then

An alternative syntax:

def validate_unique(self, exclude=None):
    exclude = exclude or []
    if 'sort_order' not in exclude:
        exclude.append('sort_order')
    return super().validate_unique(exclude=exclude)

ZOMBIE thread…

Still relevant unfortunately.

To clarify, this is required because otherwise ModelForms (such as in the admin) will reject changes to the sort_order field where it is moved into a position that is currently in use.

Note: this still sucks.

I think sort_order should always be unique or unique with another field. We could have a metaclass which inspects the model and raises warnings if this isn't the case. It's not a difficult migration to do for any model which has the wrong results at the moment.

Perhaps this would be a good candidate for the Checks framework.

@meshy any reason not to add this to the Orderable model (with an additional check / constraint based self._meta.unique_together)? That way it could check if "If your sort_order field is unique_together with something" and use this logic?

I don't see why not :)

@meshy in terms of ensuring that "the sort_order field is either unique=True, or in unique_together"

... the only approach I can think of is to use a metaclass to dynamically add the sort_order field (if it is not added by the user) and set the unique=True based on whther the e sort_order field is in unique_together or not.

The biggest issue would be the need for migrations to be created before the library is updated. This could be documented and to mitigate the pain, the app could include a setting to disable this new feature (leaving the sort_order field unique=False) for legacy projects and / or to make it easier to migrate.

#53 mitigates the need to add validate_unique to a model that subclasses Orderable and has sort_order in unique_together.

Keeping this issue open to track the need to ensure the sort_order field is either unique=True, or in unique_together.