#28073: RemoveField.state_forwards() crashes with AttributeError: 'NoneType'
object
has no attribute 'is_relation'
---------------------------------+------------------------------------
Reporter: Logan Gunthorpe | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.11
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+------------------------------------
Comment (by Carel):
I'm not sure if this is a bug for me too or simply my lack of
understanding when it comes to rolling ones own migrations, but I'm
triggering the same response. I'm converting a legacy SQLite database
(Approx. 20-30 Tables still working through it) to Django. There is a
`models.IntField` (Milliseconds since Unix/Linux Epoch) which I want to
alter to a `models.DateTimeField`. Djangos' automigrate was complaining
when I switched the table from unmanaged to managed so I'm manually
performing the following actions within a custom migration :
1. Create a new `models.DateTimeField` called "Temp"
2. Using `migrations.runPython` Iterate overall the records and convert
all the data in the original field, "Modified", to `datetime.datetime` and
assign it to new field "Temp"
3. Remove the original field "Modified" using `migrations.RemoveField`
4. Rename the temporary field "temp" to "Modified" using
`migrations.RenameField`
The process fails at Step 3 where the field being removed triggers the
error, `AttributeError: 'NoneType' object has no attribute 'is_relation'`.
Originally I was using Django 1.11.3/4 but have bumped to 1.11.7 and have
the same problem.
Based on the code posted by **PythonForce** it would seem that the loop is
not assigning an instance to `old_field`, so where it tries to assign a
value for `delay` it is breaking as there is no attribute `is_relation`
for `None`/`NoneType`. Now it seems `delay` should be a boolean value so I
would like to suggest one replace the line `delay = not
old_field.is_relation` with `delay = old_field is None and not
old_field.is_relation` then if `old_field` is `None` delay is `False` and
the relation short circuits before testing the attribute. If `old_field`
turns out to be an instance then `delay` depends upon
`old_field.is_related`, as it presently does.
{{{
def state_forwards(self, app_label, state):
new_fields = []
old_field = None
print app_label + " " + self.model_name_lower + " " + self.name
for name, instance in state.models[app_label,
self.model_name_lower].fields:
if name != self.name:
new_fields.append((name, instance))
else:
old_field = instance
state.models[app_label, self.model_name_lower].fields = new_fields
# Delay rendering of relationships if it's not a relational field
delay = not old_field.is_relation
state.reload_model(app_label, self.model_name_lower, delay=delay)
}}}
My suggestions is based upon only this snippet of code and I am not aware
of any other context that may be relevant. I will try to pull down the
sources and apply this. If successful I shall report back.
P.s. If the manner in which I have posted does not meet some guideline,
let me know I'll try to neaten it up or whatever as necessary.
--
Ticket URL: <https://code.djangoproject.com/ticket/28073#comment:15>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/065.0176c5de7e445a9c27af0f91b7da1afd%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.