Opened 6 years ago

Closed 3 years ago

#18480 closed Bug (duplicate)

Inherited model fails to handle blank field properly

Reported by: Yuval Adam Owned by:
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: navi7 Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


I just opened a stack overflow question about this, but after digging a bit this is starting to look like a bug.

Take two simple models with inheritance:

class A(models.Model):
    a = models.IntegerField(blank=True)

class B(A):
    b = models.IntegerField(blank=True)

And then in runtime:

>>> A()
<A: A object>
>>> B()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "django/db/models/", line 357, in __init__
    setattr(self, field.attname, val)
  File "django/db/models/fields/", line 271, in __set__
    (instance._meta.object_name, self.related.get_accessor_name()))
ValueError: Cannot assign None: "B.b" does not allow null values.

There should be absolutely no reason why A() is properly created, while B() should fail.

Change History (8)

comment:1 Changed 6 years ago by Yuval Adam

The issue here is a conflicting field name. This is totally irrelevant to the field being blank.

I would argue, though, that the error must be much more descriptive. And I still don't quite understand why this isn't an issue with the parent model.

comment:2 Changed 6 years ago by Aymeric Augustin

Triage Stage: UnreviewedAccepted

blank=True is irrelevant here; blank is validation-related and the example doesn't involve forms.

I reproduced the inconsistency and I agree that it's a bug.

I don't understand the comment above. yuval_a, are you sure you haven't misread the model definition?

comment:3 Changed 6 years ago by anonymous

Well, what's the bug here, in your opinion?

As far as I can tell I've made the error of having field names which are the same as model names in both examples.

It's odd that the error only reproduces on the sub-model. And the error should definitely be more descriptive.

comment:4 Changed 5 years ago by anonymous

Seems all related accessor name are not validated against existing fields.

class A(models.Model):

a = models.IntegerField()
br = models.IntegerField()

class B(models.Model):

a = models.ForeignKey(A, related_name='br')

raises an error.

Should fixing this wait till the validation changes hit?

comment:5 Changed 4 years ago by navi7

Owner: changed from nobody to navi7
Status: newassigned

comment:6 Changed 4 years ago by navi7

This is a kind of red herring.

The actual problem stems from the model coming up with the same field name as name of the derived class itself so it can have the reference to the base class. Model building then just overwrites our field. The simplest test is this:

class FruitFly(models.Model):

class CroatianFruitFly(FruitFly):
    croatianfruitfly = models.IntegerField()

fly2 = CroatianFruitFly()  #  this throws wrong exception

The error thrown is:

ValueError: Cannot assign None: "CroatianFruitFly.croatianfruitfly" does not allow null values.

And that's totally misleading.

As I'm totally new to Django, I don't know a way out of it. It seems that using the same field name as the class can be explicitly forbidden by throwing meaningful errors when the model is built. Then again, that could potentially be a breaking change.

Or, the name of the reference could be mangled somehow to not use that exact name.

Anyways, I need someone who knows the internals a bit more to look at this.

comment:7 Changed 4 years ago by navi7

Cc: navi7 added
Owner: navi7 deleted
Status: assignednew

comment:8 Changed 3 years ago by Tim Graham

Resolution: duplicate
Status: newclosed

The clashing field/model names is a duplicate of #14217.

Note: See TracTickets for help on using tickets.
Back to Top