[Django] #16732: Unable to have abstract model with unique_together

21 views
Skip to first unread message

Django

unread,
Aug 30, 2011, 5:49:03 PM8/30/11
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------+----------------------------------------------
Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Milestone: | Component: Database layer (models, ORM)
Version: 1.3 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------+----------------------------------------------
I have such model definition:

{{{
class SlugVersion(models.Model):
class Meta:
abstract = True
unique_together = (('slug', 'version'),)

slug = models.CharField(db_index=True, max_length=10, editable=False)
version = models.IntegerField(db_index=True, editable=False)

class Base(SlugVersion):
name = models.CharField(max_length=10)

class Test(Base):
test = models.IntegerField()
}}}

And I am getting:

{{{
Error: One or more models did not validate:
test.test: "unique_together" refers to slug. This is not
in the same model as the unique_together statement.
test.test: "unique_together" refers to version. This is not
in the same model as the unique_together statement.
}}}

I see this is as a bug. Why there could not be a table for class `Base`
with unique constraints on its `slug` and `version` fields, and then 1-1
relationship with additional table for model `Test` with field `test`.

--
Ticket URL: <https://code.djangoproject.com/ticket/16732>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 31, 2011, 6:26:38 PM8/31/11
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Milestone: | Component: Database layer
Version: 1.3 | (models, ORM)
Resolution: | Severity: Normal
Triage Stage: | Keywords:
Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Changes (by mitar):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

But this does work:


{{{
class SlugVersion(models.Model):
class Meta:
abstract = True
unique_together = (('slug', 'version'),)

slug = models.CharField(db_index=True, max_length=10, editable=False)
version = models.IntegerField(db_index=True, editable=False)

class Base(SlugVersion):
name = models.CharField(max_length=10)

class Test(Base):

class Meta:
unique_together = ()

test = models.IntegerField()
}}}

And also creates tables as wanted.

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:1>

Django

unread,
Aug 31, 2011, 6:50:40 PM8/31/11
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Milestone: | Component: Database layer
Version: 1.3 | (models, ORM)
Resolution: | Severity: Normal
Triage Stage: | Keywords:
Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------

Comment (by mitar):

Using such metaclass for `Base` class above solves the problem:

{{{
class ModelBaseFix(models.base.ModelBase):
def __new__(cls, name, bases, attrs):
# We simply remove all unique_together values which we find in a
parent
new_class = super(ModelBaseFix, cls).__new__(cls, name, bases,
attrs)
unique_together = list(new_class._meta.unique_together)
for parent_class in new_class._meta.parents.keys():
for parent_unique_together in
parent_class._meta.unique_together:
try:
unique_together.remove(parent_unique_together)
except ValueError:
pass
new_class._meta.unique_together = tuple(unique_together)
return new_class
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:2>

Django

unread,
Sep 5, 2011, 3:41:36 AM9/5/11
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Milestone: | Component: Database layer
Version: 1.3 | (models, ORM)
Resolution: | Severity: Normal
Triage Stage: Accepted | Keywords:
Needs documentation: 0 | Has patch: 0
Patch needs improvement: 0 | Needs tests: 0
UI/UX: 0 | Easy pickings: 0
-------------------------------------+-------------------------------------
Changes (by aaugustin):

* stage: Unreviewed => Accepted


Comment:

If I add this code below the models definition in the original report:
{{{
print SlugVersion._meta.abstract, SlugVersion._meta.unique_together
print Base._meta.abstract, Base._meta.unique_together
print Test._meta.abstract, Test._meta.unique_together
}}}
I get:
{{{
% ./manage.py validate
True (('slug', 'version'),)
False (('slug', 'version'),)
False (('slug', 'version'),)

Error: One or more models did not validate:

selftest.test: "unique_together" refers to slug. This is not in the same

model as the unique_together statement.

selftest.test: "unique_together" refers to version. This is not in the

same model as the unique_together statement.
}}}

This shows that `Test` inherits the `Meta` of `Base`, which is wrong,
because `Base` isn't abstract.

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:3>

Django

unread,
Mar 31, 2014, 3:31:11 PM3/31/14
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------

Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by anonymous):

Would this ever be fixed?

I have been avoiding the use of abstract models because of this and it
prevents the model declarations from being DRY...

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:4>

Django

unread,
Nov 25, 2014, 4:08:10 PM11/25/14
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------

Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by segfault):

* cc: segfault (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:5>

Django

unread,
Dec 1, 2014, 4:00:35 AM12/1/14
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------

Reporter: mitar | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by direx):

* cc: direx (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:6>

Django

unread,
Jun 21, 2019, 8:27:16 AM6/21/19
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: Mitar | Owner: Can
| Sarıgöl
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Can Sarıgöl):

* status: new => assigned
* owner: nobody => Can Sarıgöl
* has_patch: 0 => 1
* version: 1.3 => master


Comment:

[https://github.com/django/django/pull/11499 PR]
When I read the document about
[https://docs.djangoproject.com/en/2.2/topics/db/models/#meta-inheritance
meta-inheritance], I didn't see the topic that in {{{ abstract = False }}}
case What happens to child meta? as far as I could see from
[https://github.com/django/django/blob/a9179ab032cda80801e7f67ef20db5ee60989f21/django/db/models/base.py#L144
code], {{{ordering}}} and {{{get_latest_by}}} always moving in child meta
in every situation. Should we change the code like my PR + document about
{{{ abstract = False }} and fix the blown up test?

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:7>

Django

unread,
Jul 5, 2019, 9:16:24 AM7/5/19
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: Mitar | Owner: Can
| Sarıgöl
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* needs_better_patch: 0 => 1


Comment:

Topic for `abstract = False` is not a part of "Abstract base classes"
documentation (see [https://docs.djangoproject.com/en/2.2/topics/db/models
/#meta-and-multi-table-inheritance meta-and-multi-table-inheritance]).
Falling tests show that it is not a proper solution. `('suffix1',
'suffix2')` should be inherited from an abstract class `BookXtra`. I'm
afraid that proposed change is strongly backward incompatible.

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:8>

Django

unread,
Jul 5, 2019, 10:09:21 AM7/5/19
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: Mitar | Owner: Can
| Sarıgöl
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Can Sarıgöl):

* needs_better_patch: 1 => 0


Comment:

I got your backward-incompatible concern. I added a case for classes that
have more than one inherited classes and abstract at least one. this can
solve BookXtra test.

--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:9>

Django

unread,
Mar 26, 2020, 4:55:56 AM3/26/20
to django-...@googlegroups.com
#16732: Unable to have abstract model with unique_together
-------------------------------------+-------------------------------------
Reporter: Mitar | Owner: Can
| Sarıgöl
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* needs_tests: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/16732#comment:10>

Reply all
Reply to author
Forward
0 new messages