Hello,
project was written in django 1.6 and recently migrated to django 1.8.15. It works quite well but project tests showed a failure during executing line:
objs = Agent.objects.filter(Q(first_name__icontains=term) | Q(last_name__icontains=term) | Q(accord_id__icontains=term) | Q(company__icontains=term))
Traceback (most recent call last):
File ".../project/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../project/local/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 57, in dispatch
return super(Select2View, self).dispatch(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/views/generic/base.py", line 89, in dispatch
return handler(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 76, in get
self.get_results(request, term, page, context)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 194, in get_results
return field.get_results(request, term, page, context)
File ".../project/project/app/fields.py", line 33, in get_results
objs = Agent.objects.filter(Q(first_name__icontains=term) | Q(last_name__icontains=term) | Q(accord_id__icontains=term) | Q(company__icontains=term))
File ".../project/local/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/db/models/query.py", line 679, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/db/models/query.py", line 697, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1310, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1332, in _add_q
current_negated, allow_joins, split_subq)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1338, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1150, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1036, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1407, in names_to_path
for int_model in opts.get_base_chain(model):
TypeError: 'NoneType' object is not iterable
Internal Server Error: /some/json/file.json
Traceback (most recent call last):
File ".../project/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../project/local/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 57, in dispatch
return super(Select2View, self).dispatch(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/views/generic/base.py", line 89, in dispatch
return handler(request, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 76, in get
self.get_results(request, term, page, context)
File ".../project/local/lib/python2.7/site-packages/django_select2/views.py", line 194, in get_results
return field.get_results(request, term, page, context)
File ".../project/project/app/fields.py", line 33, in get_results
Q(company__icontains=term))
File ".../project/local/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/db/models/query.py", line 679, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File ".../project/local/lib/python2.7/site-packages/django/db/models/query.py", line 697, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1310, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1332, in _add_q
current_negated, allow_joins, split_subq)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1338, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1150, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1036, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File ".../project/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1407, in names_to_path
for int_model in opts.get_base_chain(model):
TypeError: 'NoneType' object is not iterable
But in django 1.6 all works well. So i make some inspection.
In project there is a class Agent (class Agent(AbstractUser, AnotherClass):), metaclass Agent2Metaclass (class Agent2Metaclass(models.base.ModelBase):) and class Agent2 (class Agent2(TimeStampedModel):) using Agent2Metaclass:
class Agent(AbstractUser, AnotherClass):
....
CHANGE_FIELDS_WITH_APPROVAL= ('first_name', 'last_name', 'email', ... )
....
class Agent2Metaclass(models.base.ModelBase):
def __new__(cls, name, bases, attrs):
attrs = collections.OrderedDict(attrs)
for field in Agent.CHANGE_FIELDS_WITH_APPROVAL:
attrs[field] = Agent._meta.get_field(field)
return super(Agent2Metaclass, cls).__new__(cls, name, bases, attrs)
class Agent2(TimeStampedModel):
__metaclass__ = Agent2Metaclass
agent = models.OneToOneField(Agent)
....
And now what is going on showed in console:
Django 1.6:
In [1]: from app.models import Agent
In [2]: print Agent._meta.fields
[<django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: password>, <django.db.models.fields.DateTimeField: last_login>, <django.db.models.fields.BooleanField: is_superuser>, <django.db.models.fields.CharField: username>, ...]
In [3]: print Agent._meta.fields[2]
<django.db.models.fields.DateTimeField: last_login>
In [4]: print Agent._meta.fields[3]
<django.db.models.fields.BooleanField: is_superuser>
In [5]: print Agent._meta.fields[4]
<django.db.models.fields.CharField: username>
In [6]: print Agent._meta.fields[5]
<django.db.models.fields.CharField: first_name>
In [7]: print Agent._meta.fields[6]
<django.db.models.fields.CharField: last_name>
In [8]: print type(Agent._meta.fields[6])
<class 'django.db.models.fields.CharField'>
In [9]: print Agent._meta.fields[3]
<django.db.models.fields.BooleanField: is_superuser>
In [10]: print Agent._meta.fields[3].__class__
<class 'django.db.models.fields.BooleanField'>
In [11]: print Agent._meta.fields[3].__class__.__class__
<type 'type'>
In [12]: print Agent.objects.filter(first_name="Petr")
[<Agent: John Adams>, <Agent: Igor Hnizdo>, '...(remaining elements truncated)...']
Django 1.8:
In [1]: from app.models import Agent
In [2]: print Agent._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: password>, <django.db.models.fields.DateTimeField: last_login>, <django.db.models.fields.BooleanField: is_superuser>, <django.db.models.fields.CharField: username>, <django.db.models.fields.CharField: first_name>, ...)
In [3]: print Agent._meta.fields[1]
app.Agent.password
In [4]: print Agent._meta.fields[2]
app.Agent.last_login
In [5]: print Agent._meta.fields[3]
app.Agent.is_superuser
In [6]: print Agent._meta.fields[4]
app.Agent.username
In [7]: print Agent._meta.fields[5]
app.Agent2.first_name
#this seems to me as strange behaviour - why is field of Agent presented as field of Agent2?
In [8]: print Agent._meta.fields[5].__class__
<class 'django.db.models.fields.CharField'>
In [9]: print Agent._meta.fields[4].__class__
<class 'django.db.models.fields.CharField'>
In [10]: from app.models import Agent2
In [11]: print Agent2.objects.filter(first_name="Petr")
[<Agent2: Petr Pavel>, <Agent2: Petr Petrovic>, <Agent2: Petr Cech>, ...]
In [12]: print Agent.objects.filter(first_name="Petr")
--------------------------------------------------------------------------------------------------------------------------------
TypeError Traceback (most recent call last)
and errors like above are shown.
It seems like fields of Agent were changed during execution of Agent2Metaclass in order to set _forward_fields_map[] in django.db.models.options. Fields of Agent are set to Agent before executing the Agent2Metaclass.
And the error appears in django.db.models.sql.query in def names_to_path because opts.get_base_chain(model) is None or NoneType.
If i paste a condition "if opts.get_base_chain(model) is not None:" before the for cycle it seems it works ok. But it is a good solution?
It is OK when some fields of Agent are set as fields of Agent2 after executing Agent2Metaclass?
It is a good behaviour of django, that the Agent.object.filter(first_name="Petr") ends with error?
If i am wrong, how can i filter Agent?
Thank you.
===========================================================================================================
===========================================================================================================
===========================================================================================================
List from def names_to_path (before my if condition) during Agent.object.filter("somestring") in django 1.6:
-------------------------------
model: None
names: ['session_key']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: None
names: ['expire_date']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: None
names: ['pk']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: None
names: ['first_name']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: None
names: ['last_name']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: None
names: ['company']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: None
names: ['date_joined']
opts: app.agent
opts.model: <class 'app.models.Agent'>
List from def names_to_path (before my if condition) during Agent.object.filter("somestring") in django 1.8:
-------------------------------
model: <class 'django.contrib.sessions.models.Session'>
names: ['session_key']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: <class 'django.contrib.sessions.models.Session'>
names: ['session_key']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: <class 'django.contrib.sessions.models.Session'>
names: ['expire_date', 'gt']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: <class 'django.contrib.sessions.models.Session'>
names: ['expire_date']
opts: sessions.session
opts.model: <class 'django.contrib.sessions.models.Session'>
-------------------------------
model: <class 'app.models.Agent'>
names: ['pk']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent'>
names: ['pk']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['first_name', 'icontains']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['first_name']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['last_name', 'icontains']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['last_name']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['company', 'icontains']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent2'>
names: ['company']
opts: app.agent
opts.model: <class 'app.models.Agent'>
-------------------------------
model: <class 'app.models.Agent'>
names: ['date_joined']
opts: app.agent
opts.model: <class 'app.models.Agent'>