Django 1.8 - FieldError: Cannot resolve keyword into field - django

I recently upgraded from Django 1.6 to Django 1.8. When I did, I found that I was no longer able to to do a lookup back through a foreign key relationship as described in:
https://docs.djangoproject.com/en/1.8/topics/db/queries/#lookups-that-span-relationships.
The system is set up so that there are two projects which use the same database. (Not my idea, but not something I would like to change right now.) The project where the models were initially created and migrated works just fine after the upgrade, but the other one does not. The models file for each is identical.
Models.py:
class Site(models.Model):
name = models.CharField(max_length=255)
class Meta:
app_label = 'project1'
class Page(models.Model):
title = models.CharField(max_length=255)
site = models.ForeignKey('Site')
class Meta:
app_label = 'project1'
Error traceback from the Django Shell:
>>> x = models.Site.objects.filter(page__id=1000)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/user_name/project2/venv/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 "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 679, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/user_name/project2/venv/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 "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1314, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1342, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1154, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1035, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1401, in names_to_path
"Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'page' into field. Choices are: name, id
In the first project, the same query works as expected:
>>> x = models.Site.objects.filter(page__id=1000)
[<Site: http://stackoverflow.com>]

What if you set a related_name on the `ForeignKey ?
class Page(models.Model):
site = models.ForeignKey('Site', related_name="pages") # Note the related_name here
I tried it on another project and it work as axpected:
>>> Site.objects.filter(pages__pk=42)
[<Site: http://stackoverflow.com>]
If you don't set a related_name, I think the default is <model>_set. So it should be page_set.

I am new to Django, don't know if this helps but I had same issue. In my case, it was typing error.
I had written this earlier:
Question.objects.filter(question_text_startswith='What')
In Django documentation, I noticed there should be 2 underscores before the lookup startswith:
Question.objects.filter(question_text__startswith='What')

Related

TypeError and AssertionError after upgrade to Django 2

I'm tasked with upgrading a Django REST framework project from Django 1.8 to Django 2.x. I already ported the whole code from python 2.7 to python 3.7 and from Django 1.8 to 2.0.13. I'm using virtual envs.
I got it running on python 3.7 and Django 2.0.13, and RESTframework 3.11, although I ran into problems while trying to create new objects.
Here's the Traceback to my problem:
Traceback (most recent call last):
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\user1\projects\proj_py3\rest_framework\viewsets.py", line 114, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\user1\projects\proj_py3\rest_framework\views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "C:\Users\user1\projects\proj_py3\rest_framework\views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\user1\projects\proj_py3\rest_framework\views.py", line 476, in raise_uncaught_exception
raise exc
File "C:\Users\user1\projects\proj_py3\rest_framework\views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\user1\projects\proj_py3\rest_framework\mixins.py", line 18, in create
serializer.is_valid(raise_exception=True)
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 219, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 418, in run_validation
value = self.to_internal_value(data)
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 471, in to_internal_value
for field in fields:
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 354, in _writable_fields
for field in self.fields.values():
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\utils\functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 348, in fields
for key, value in self.get_fields().items():
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 1027, in get_fields
field_names = self.get_field_names(declared_fields, info)
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 1128, in get_field_names
serializer_class=self.__class__.__name__
AssertionError: The field 'participantIDs' was declared on serializer OrderSerializer, but has not been included in the 'fields' option.
I don't understand why that exception only occurs in the new version of the code, since I didn't change the models, serializers, or views, aside from the version updates.
this is what the problematic serializer looks like:
class OrderSerializer(serializers.ModelSerializer):
created_by = ShortPersonSerializer(read_only=True, required=False)
modified_by = ShortPersonSerializer(read_only=True, required=False)
customer = OrderPersonSerializer(required=False, allow_null=True, partial=True)
...
...
participantIDs = serializers.SlugRelatedField(many=True, required=False, allow_null=True, slug_field='id', source='participants', queryset=Person.objects.all())
...
...
class Meta:
model = Order
fields = ('id', 'title','customer',
'customer_copy_id', 'customer_copy_salutation', 'customer_copy_first_name', 'customer_copy_last_name', 'created_at', 'created_by', 'modified_at', 'modified_by')
def create(self, validated_data):
customer_data = validated_data.pop('customer', None)
participants_data = validated_data.pop('participants', None)
if customer_data and customer_data is not None:
validated_data['customer'] = Person(pk=customer_data['id'])
order = Order.objects.create(**validated_data)
if participants_data and participants_data is not None:
setattr(order, 'participants', participants_data) # line 1
order.save() # line 2
...
Additional info:
Before this error was detected, I got a different error, with the following traceback:
Traceback (most recent call last):
...
...
File "C:\Users\user1\projects\proj_py3\rest_framework\serializers.py", line 204, in save
self.instance = self.create(validated_data)
File "C:\Users\user1\projects\proj_py3\orders\serializers.py", line 90, in create
setattr(order, 'participants', participants_data)
File "C:\Users\user1\Envs\projpy3\lib\site-packages\django\db\models\fields\related_descriptors.py", line 509, in __set__
% self._get_set_deprecation_msg_params(),
TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use participants.set() instead.
so I had changed the serializer like this:
...
...
if participants_data and participants_data is not None:
#setattr(order, 'participants', participants_data) # line 1
order.save() # line 2
order.participants.set(participants_data)
...
ever since I've done that, I get the AssertionError instead of the TypeError, and I don't know how to revert that problem. Ofcourse I changed the code back, but I've also deleted all the compiled files in the project directory, I deleted the virtual env and created a new one, I ran a disk cleanup on Windows, I even uninstalled Python37 in order to install it again. Always rebooting inbetween. All to no avail.
UPDATE:
I compared the update and create methods in my project's serializers.py files with the ones in rest_framework version I'm using: rest_framework/serializers.py on GitHub
I changed them according to the newer version of the Django REST framework (the code was developed for an older version).
I also checked all the serializers of the other Apps in the project, and I found out, that all but the concerned App orders had the attribute participantsID in their Serializer's Meta class, in case it's supposed to access the other App through the other's Serializer.
In that case, it's like suggested in the comments: the AssertionError was there all along.
There is nothing else to do but to add the attribute to fields.
Add participantIDs to your fields attribute of OrderSerializer's Meta class
class OrderSerializer(serializers.ModelSerializer):
# other code snippets
class Meta:
model = Order
fields = (other-fields, 'participantIDs')
# other code snippets

Error while select_related query

I have Question and QuestionChoices models as below, when I try to retrieve the Question and related Answers from the Questionchoices I get the below error saying that the query is expecting string. What could be wrong model/query?
class Question(models.Model):
Question_Id = models.AutoField(primary_key=True)
Question_Text = models.TextField(max_length=1000)
def __str__(self):
return self.Question_Text
def __int__(self):
return self.Question_Id
class QuestionChoices(models.Model):
Choice_Id = models.AutoField(primary_key=True)
Question_Choices_Question_Id = models.ForeignKey("Question", on_delete=models.CASCADE)
Choice = models.TextField(max_length=500)
Is_Right_Choice = models.BooleanField(default=False)
>>> QuestionChoices.objects.select_related().filter(Question_Choices_Question_Id = Question.Question_Id)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 836, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 854, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1253, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1277, in _add_q
split_subq=split_subq,
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1215, in build_filter
condition = self.build_lookup(lookups, col, value)
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1085, in build_lookup
lookup = lookup_class(lhs, rhs)
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\lookups.py", line 18, in __init__
self.rhs = self.get_prep_lookup()
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\fields\related_lookups.py", line 115, in get_prep_lookup
self.rhs = target_field.get_prep_value(self.rhs)
File "C:\Users\adm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\fields\__init__.py", line 947, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'DeferredAttribute'
I got the same error after running your shell command. The problem is caused by the way the code's filter() is set-up. The argument requires a model object OR foreign key as the value.
Answer:
python3 manage.py shell
>>> from my_app.models import *
>>> my_question_obj = Question.objects.create(Question_Text = "This is my question")
>>> QuestionChoices.objects.select_related().filter(Question_Choices_Question_Id=my_model_obj)
Alternatively if you already have a question you would like to filter on in your database you can use get() to retrieve the object.
python3 manage.py shell
>>> from my_app.models import *
>>> my_question_obj = Question.objects.get(Question_Text="This is the text of your question")
>>> QuestionChoices.objects.select_related().filter(Question_Choices_Question_Id = my_model_obj)

Integrity error - get_or_create says cannot be NULL on importing data

I asked a question to try and fix an issue I was having where I didn't understand how to use ForeignKeys properly. That was very helpfully fixed, although I had a subsequent problem with django.db.utils.IntegrityError: core_team.blahblah_id may not be NULL and I decided to roll back, do something slightly simpler - in order to avoid a double lookup (Match is linked to both Team and League), I would write a management command to import the teams.
On my (clearly flawed) understanding from the previous question, I've done it right - it uses get_or_create to check for the league instance and then assigns the team based on that. I've also doublechecked that the DB is up to date (I'm running south and did the forward migration the last time I changed the scheme, nothing's changed since then. Last change was to make the names in both models the primary key (as there's only one team of each name, only one league of each name.)
Most recently, I've added code to provide the default to the team get_or_create section, but am receiving the same error. I understand the cause (I think) of the error - that the ForeignKey 'league' in Team already exists in the database, and can't be null inserting another team (from https://docs.djangoproject.com/en/1.5/ref/models/querysets/#get-or-create), just not how to fix it.
Management command:
from django.core.management.base import BaseCommand, CommandError
import csv
import csvImporter
#from core.models import Match
from time import strptime
from datetime import datetime
master_data = open ('/Users/chris/Desktop/AllDataTruncated.csv', 'r')
data = list(tuple(rec) for rec in csv.reader(master_data, delimiter=','))
from core.models import League, Team
team_list = []
for row in data:
if row[2] == "HomeTeam":
print "Continuing"
continue
elif row[2] == "":
print "Continuing"
continue
else:
league, _ = League.objects.get_or_create(name=row[0])
print league
team, _ = Team.objects.get_or_create(team_name=row[2], defaults={'league':league})
current_team = Team(league = league, team_name=team)
print current_team
And relevant bits of models.py:
class League (models.Model):
name = models.CharField(max_length=2, primary_key=True)
last_modified = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
class Team(models.Model):
team_name = models.CharField(max_length=50, primary_key=True)
league = models.ForeignKey(League)
team_colour = models.CharField(max_length=6, null=True, blank=True)
def __unicode__(self):
return unicode (self.team_name)
The full traceback is:
$ python manage.py importteams
Continuing
E0
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 453, in execute_from_command_line
utility.execute()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 272, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 77, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/chris/Dropbox/Django/gmblnew/core/management/commands/importteams.py", line 26, in <module>
team2, _ = Team.objects.get_or_create(team_name=row[3])
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/manager.py", line 146, in get_or_create
return self.get_query_set().get_or_create(**kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 487, in get_or_create
six.reraise(*exc_info)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 477, in get_or_create
obj.save(force_insert=True, using=self.db)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/base.py", line 546, in save
force_update=force_update, update_fields=update_fields)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/base.py", line 650, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/manager.py", line 215, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 1661, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 937, in execute_sql
cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/util.py", line 41, in execute
return self.cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 364, in execute
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 362, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: core_team.league_id may not be NULL
Now - I think that it's odd that it's saying league_id here, as this shouldn't be relevant anymore? When I did the migration, the question came up:
? The field 'League.id' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now.
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception; you can edit the migration to fix it later
? Please select a choice: 3
Is this what's perpetuating this issue?
Edit: Seems not. Dropped the DB and moved the South migrations folder, and it's still doing it. The source CSV is also fine (no blank lines or empty strings/segments), and the code above has a section to skip those segments anyway; it's not getting that far.
Ugh. The answer to this, for any other newbies who are coming to it later, is actually ludicrously simple. What I'm doing here is creating an entry in the table 'Team', which has a ForeignKey going back to 'League'.
The 'trick' (it's not a trick, just really badly explained in the documentation, imho) is that you need to explicitly pass the league back when you do the get_or_create for the Team object. It's not just about matching the team name
I thought I'd done this, but I hadn't, it appears. This code works (and quite effectively ensures there are no duplicates):
for row in data:
if row[2] == "HomeTeam":
print "Continuing"
continue
elif row[2] == "":
print "Continuing"
continue
else:
league, _ = League.objects.get_or_create(name=row[0])
print league
team, _ = Team.objects.get_or_create(team_name=row[2], league=league)
current_team = Team(league = league, team_name=team)
print current_team

django-taggit deep relationship query

I'm using django-taggit and I came upon a problem when trying to filter across relationships.
Having the following models:
class Artist(models.Model):
tags = TaggableManager()
class Gig(models.Model):
artist = models.ManyToManyField(Artist)
What I would like to achieve is the get all gigs who's artist(s) have a specific tag.
I thought this would be easy and eagerly wrote:
Gig.objects.filter(artist__tags__name__in=["rock"])
Which gave me:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/manager.py", line 141, in filter
return self.get_query_set().filter(*args, **kwargs)
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/query.py", line 550, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/query.py", line 568, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1172, in add_q
can_reuse=used_aliases, force_having=force_having)
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1139, in add_filter
process_extras=False)
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1060, in add_filter
negate=negate, process_extras=process_extras)
File "/home/jonas/.virtualenvs/wsw/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1238, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'tagged_items' into field. Choices are: artist, date, id, location, url
I managed to fix it by commenting out TaggableManager.extra_filters() in manage.py.
Take it with a grain of salt, because I have no idea what I may have broken by doing this.
Getting all Gigs for who's Artist's have a specific tag.
artists = Artist.objects.filter(tags__name__in=["rock"])
gigs = Gig.objects.filter(artist__in=artists)

Django generic relation field reports that all() is getting unexpected keyword argument when no args are passed

I have a model which can be attached to to other models.
class Attachable(models.Model):
content_type = models.ForeignKey(ContentType)
object_pk = models.TextField()
content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")
class Meta:
abstract = True
class Flag(Attachable):
user = models.ForeignKey(User)
flag = models.SlugField()
timestamp = models.DateTimeField()
I'm creating a generic relationship to this model in another model.
flags = generic.GenericRelation(Flag)
I try to get objects from this generic relation like so:
self.flags.all()
This results in the following exception:
>>> obj.flags.all()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/django/db/models/manager.py", line 105, in all
return self.get_query_set()
File "/usr/local/lib/python2.6/dist-packages/django/contrib/contenttypes/generic.py", line 252, in get_query_set
return superclass.get_query_set(self).filter(**query)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 498, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 516, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1675, in add_q
can_reuse=used_aliases)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1569, in add_filter
negate=negate, process_extras=process_extras)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1737, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'object_id' into field. Choices are: content_type, flag, id, nestablecomment, object_pk, timestamp, user
>>> obj.flags.all(object_pk=obj.pk)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: all() got an unexpected keyword argument 'object_pk'
What have I done wrong?
You need to define object_id_field and content_type_field when creating GenericRelation:
flags = generic.GenericRelation(Flag, object_id_field="object_pk", content_type_field="content_type")