FieldError: Cannot resolve keyword 'XXXX' into field - python

This is a very strange error. I only receive it on my heroku server.
Here is how my model is:
# Abstract Model
class CommonInfo(models.Model):
active = models.BooleanField('Enabled?', default=False)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Country(CommonInfo):
name = models.CharField('Country Name', db_index=True, max_length=200, help_text='e.g. France')
official_name = models.CharField('Official Name', max_length=400, blank=True, help_text='e.g. French Republic')
population = models.IntegerField('Population', help_text='Population must be entered as numbers with no commas or separators, e.g. 39456123', null=True, blank=True)
alpha2 = models.CharField('ISO ALPHA-2 Code', max_length=2, blank=True)
class News(CommonInfo):
title = models.CharField('Title', max_length=250)
slug = models.CharField('slug', max_length=255, unique=True)
body = models.TextField('Body', null=True, blank=True)
excerpt = models.TextField('Excerpt', null=True, blank=True)
author = models.ForeignKey(Author)
country = models.ManyToManyField(Country, null=True, blank=True)
def __unicode__(self):
return self.title
When I try to access News items from Admin site on my production server, I get this error (everything works fine on my dev server):
FieldError: Cannot resolve keyword 'news' into field. Choices are: active, alpha2, date_created, date_updated, id, name, official_name, population
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/query.py", line 687, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1271, in add_q
can_reuse=used_aliases, force_having=force_having)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1139, in add_filter
process_extras=process_extras)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1337, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
I run the same django (1.5.4) and python (2.7.2) versions on my production and development environments.
My production server is Heroku
Any ideas what could triggers the error?
UPDATE:
admin.py config is as follow:
from django.contrib import admin
from APP.models import Country, News
class NewsForm(ModelForm):
class Meta:
model = News
class NewsAdmin(ModelAdmin):
form = NewsForm
search_fields = ['title',
'country__name']
list_filter = ('country',
'active'
)
list_per_page = 30
list_editable = ('active', )
list_display = ('title',
'active'
)
list_select_related = True
prepopulated_fields = {"slug": ("title",)}
admin.site.register(Country)
admin.site.register(News, NewsAdmin)

Finally, I was able to resolve the issue.
First, I managed to replicate the error in my local environment. At first, I was testing the application using built-in Django runserver. However, my production environment is Heroku that uses Gunicorn as webserver. When I switched to Gunicorn and foreman on my local server, I was able to replicate the error.
Second, I tried to pin point the issue by going through the models and add/remove different components, fields. To explain the process better, I have to add a missing piece to the original question.
The description I had posted above is kind of incomplete. I have another model in my models.py that I did not include in my original question, because I thought it was not relevant. Here is the complete model:
# Abstract Model
class CommonInfo(models.Model):
active = models.BooleanField('Enabled?', default=False)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Country(CommonInfo):
name = models.CharField('Country Name', db_index=True, max_length=200, help_text='e.g. France')
official_name = models.CharField('Official Name', max_length=400, blank=True, help_text='e.g. French Republic')
population = models.IntegerField('Population', help_text='Population must be entered as numbers with no commas or separators, e.g. 39456123', null=True, blank=True)
alpha2 = models.CharField('ISO ALPHA-2 Code', max_length=2, blank=True)
def get_country_names():
names = Country.objects.only('name').filter(active=1)
names = [(str(item), item) for item in names]
return names
class Person(CommonInfo):
name = models.CharField(max_length=200)
lastname = models.CharField(max_length=300)
country = models.CharField(max_length=250, choices=choices=get_country_names())
class News(CommonInfo):
title = models.CharField('Title', max_length=250)
slug = models.CharField('slug', max_length=255, unique=True)
body = models.TextField('Body', null=True, blank=True)
excerpt = models.TextField('Excerpt', null=True, blank=True)
author = models.ForeignKey(Author)
country = models.ManyToManyField(Country, null=True, blank=True)
def __unicode__(self):
return self.title
My model design didn't require a ForeignKey for Person's table, so I had decided to go with a simple CharField and instead, use a regular drop down menu. However, for some reason, Gunicorn raises the above mentioned error when, as part of the get_country_names(), the Country table is called before News. As soon as I deleted the get_country_names() and turned the country field on Person table into a regular CharField the issue was resolved.
Reading through the comments in this old Django bug and this post by Chase Seibert considerably helped me in this process.
Although ticket#1796 appears to be fixed more than 6 years ago, it seems that some tiny issues still remain deep buried there.
Thats it! Thanks everyone.

Adding to the possible situations under which this happens. I searched for the field that could not be found in any of my models.
Searching on the code I found that I was annotating a queryset with such field and then feeding that queryset as an __in search to another (along other complex queries).
My work around was to change that annotated queryset to return IDs and use that. On this particular case that result was always going to be small so the list of IDs was not a problem to pass.

I'd had some ManyToMany relationships that were working one-way. I had been messing around with my settings and changing the name of the main application a couple times. Somewhere along the lines, I had removed it from the INSTALLED_APPS section! Once I added that back in, then it worked. Definitely PEBKAC, but maybe this will help someone some day. It took me a while to think of checking for that, since the app was mostly working.
For example, my app is called deathvalleydogs. I had two models:
class Trip(ModelBase):
dogs = models.ManyToManyField(Dog, related_name="trips")
class Dog(ModelBase):
name = models.CharField(max_length=200)
when I tried to show a template for a Trip listing the Dogs that were on the trip like this:
{% for dog in trip.dogs.all %}
<li>{{ dog.name }}</li>
{% endfor %}
then I got an error of:
Cannot resolve keyword u'trips' into field. Choices are: active, birth_date, ...
Though I was still able to show a template for a Dog listing the trips they were on. Notice that trips should have been a field created by the m2m on the Dog objects. I wasn't referencing that field in the template, but it barfed on that field anyway in debug mode.
I wish the error had been more explicit, but I'm just so happy I finally found my mistake!!!

You can try to reset migrations:
Remove the all migrations files within your project.
Go through each of your projects apps migration folder (your_app/migrations/) and remove everything inside, except the init.py file.
Run makemigrations and migrate.

I was using the wrong dunder lookup on an admin model search field, so for example:
Not working:
class SomeAdmin(admin.ModelAdmin):
list_display = (
"id",
"thing_id",
"count",
"stuff_name",
"stuff_id"
)
readonly_fields = ("count")
# These cannot be resolved, because "stuff" doesn't exist on the model
search_fields = ("stuff__name", "stuff__id")
def stuff_name(self, obj):
return obj.thing.stuff.name
def stuff_id(self, obj):
return obj.thing.stuff.id
def get_queryset(self, request):
return super().get_queryset(request).select_related("thing")
Working:
class SomeAdmin(admin.ModelAdmin):
list_display = (
"id",
"thing_id",
"count",
"stuff_name",
"stuff_id"
)
readonly_fields = ("count")
search_fields = ("thing__stuff__name", "thing__stuff__id", "thing__id")
def stuff_name(self, obj):
return obj.thing.stuff.name
def stuff_id(self, obj):
return obj.thing.stuff.id
def get_queryset(self, request):
return super().get_queryset(request).select_related("thing")

I had this error. And if your are using POSTMAN to do an API call to a URL, then you may be encountering this same error.
django.core.exceptions.FieldError: Cannot resolve keyword 'player' into field. Choices are ...
Either in your model or serializer, you are referring to a particular field e.g. player in my case as you would when it is referenced as a foreign key.
In my case I had a Player model, and I wanted to update the reference in the save method of a Market model, when a weight is changed in the market, it should reflect immediately on the player.
class Market(models.Model):
player = models.ForeignKey(Player)
weight = models.CharField('Weight')
...
def save(self):
if self.weight:
# wrong
Player.objects.get(player=self.player) # this object reference of itself does not exist, hence the error
# right
Player.objects.get(pk=self.player.pk)
...
super().save()

Related

Unable to delete object from Django admin panel with MongoDB

I have a Django project using a MongoDB connected by Djongo. I created a simple model which looks like:
from django.db import models
# Create your models here.
class Property(models.Model):
name = models.CharField(max_length=128, blank=False)
property_type = models.CharField(max_length=24, blank=True)
include_on = models.CharField(max_length=256, blank=True)
format_example = models.TextField(blank=True)
notes = models.TextField(blank=True)
After registering the model by using the line admin.site.register(Property) in the admin.py file I end up seeing my model appear. After adding a test Property I see the line
The property “Property object (61226db9f4f416b206c706e5)” was added successfully.
Which tells me the item was added. It also appears on the admin panel but it looks like:
Property object (None)
If I select the property I get an error that says:
Property with ID “None” doesn’t exist. Perhaps it was deleted?
If I try to delete the property I get a ValueError with error of:
Field 'id' expected a number but got 'None'.
Since I am currently learning Django/MongoDB I actually ran across the ValueError once before. The fix was to delete the entire database and start over. The issue is I don't want to run into this in the future and want to know what I have to do to fix it, or correct what I am doing wrong.
I found my answer. Turns out I need to assign a primary key. I fixed this by changing my model to..
class Property(models.Model):
name = models.CharField(primary_key=True, max_length=128, blank=False)
property_type = models.CharField(max_length=24, blank=True)
include_on = models.CharField(max_length=256, blank=True)
format_example = models.TextField(blank=True)
notes = models.TextField(blank=True)

how edit names of field in django filters, and add styling

I am following a tutorial to make a django app, I was making a filter table however there are some issues in it. I have already tried things suggested in other answers, and they did not work for me.
In the image attached as you can see I have underlined the names of the fields that I want to change and don't know how to do it, django just named those fileds by itslef and I want to change it, also please tell how can I use bootstrap to make it look good. Thank you..
filters.py file -
import django_filters
from django_filters import DateFilter, CharFilter
from . models import *
class OrderFilter(django_filters.FilterSet):
start_date = DateFilter(field_name="date_created", lookup_expr="gte") # lookup_expression, gte->
# greater than or equal to
end_date = DateFilter(field_name="date_created", lookup_expr="gte") # lookup_expression, lte-> less
# than or equal to
note = CharFilter(field_name="note", lookup_expr="icontains")
class Meta:
model = Order
fields = '__all__'
# we are excluding these because we want to customize them
exclude = ['customer', 'date_created']
model - Order - in models.py -
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for Delivery', 'Out for Delivery'),
('Delivered', 'Delivered')
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=100, null=True, choices=STATUS)
note = models.CharField(max_length=1000, null=True)
def __str__(self):
return self.product.name
Doing something like this will surely help you. You can update the name of the field in __init__ method like I did for note.
class OrderFilter(django_filters.FilterSet):
class Meta:
model = Order
fields = '__all__'
exclude = ['customer', 'date_created']
def __init__(self, *args, **kwargs):
super(OrderFilter, self).__init__(*args, **kwargs)
self.filters['note'].extra.update(
{'empty_label': 'Note'})
#Prabhjot Singh already answered the first question which is how to change the labeling of the fields... As for styling them with bootstrap a great way would be to install Django-crispy-forms and then use it when rendering the form in your template, check the documentation to know how to use it... https://django-crispy-forms.readthedocs.io/en/latest/ if you still are facing problems with it, comment below I will share a full guide tomorrow if you need it.

Check the results of one queryset against the results of another queryset django

In my django application I have three models, People, Reviews and File.
class People(models.Model):
firstname = models.charField(max_length=20)
lastname = models.charField(max_length=20)
class Reviews(models.Model):
STATUSES = (
('pending', 'Pending'),
('approved', 'Approved'),
('rejected', 'Rejected')
)
person = models.OneToOneField(People, on_delete=models.CASCADE, primary_key=True)
status = models.CharField(max_length=10, choices=STATUSES, default='pending')
comment = models.TextField()
class File(models.Model):
owner = models.OneToOneField(Reviews, on_delete=models.CASCADE, primary_key=True)
comment = models.TextField()
issue_date = models.DateField(auto_now_add=True)
See that OneToOneField on the File model? I need to be able to filter that dropdown, based on two conditions.
It needs to only display records from the Reviews model that have a status of approved.
Reviews.objects.filter(status="approved")
The displayed results must not already exist in the File model's records.
File.objects.all()
And also, while creating an instance of the File model, when a value is selected from the dropdown, how could I automatically populate the comment field with the value from the Review model's comment field?
I can't quite figure it out.
I think you can try like this:
Reviews.objects.filter(status="approved", file__isnull=True)
Here due to OneToOne relationship, all reviews object has a file attribute which returns a File Object. I am using isnull to check if it is empty or not.
Update
IMHO, I don't see why the value of the comment should be stored twice in the Database. If you have the comment value in Review, then you can access it like this:
file = File.objects.first()
comment = file.review.comment
Now, when it comes to showing it in admin site while creating File Instance, its not possible to do that without using Javascript. But another hackish approach is to display that value in the review dropdown. But for that, you need to override the __str__ method of Review Model. Like this:
class Reviews(models.Model):
STATUSES = (
('pending', 'Pending'),
('approved', 'Approved'),
('rejected', 'Rejected')
)
person = models.OneToOneField(People, on_delete=models.CASCADE, primary_key=True)
status = models.CharField(max_length=10, choices=STATUSES, default='pending')
comment = models.TextField()
def __str__(self):
return "{}: {}".format(self.status, self.comment)
But, if a file instance is created, or if you want to show comment in the file list in admin site, you can do that like this:
from django.contrib import admin
class FileAdmin(admin.ModelAdmin):
list_display = ('issue_date', 'comment')
def comment(self, obj):
return obj.review.comment
admin.site.register(File, FileAdmin)

Shows "Unable to get repr for <class 'django.db.models.query.QuerySet'>" while retrieving data

I've been trying to retrieve all data from model StudentInfo.
But it shows the following error.
django.db.utils.ProgrammingError: column student_studentinfo.gurdians_mobile does not exist
allStudent
Error in formatting: ProgrammingError: column student_studentinfo.gurdians_mobile does not exist
LINE 1: ...ile_no1", "student_studentinfo"."current_address", "student_s...
After debugging my code, I found the line that causes error is
allStudent = StudentInfo.objects.all()
And the debugging messages Shows:
Unable to get repr for class 'django.db.models.query.QuerySet'
Here is my model StudentInfo
class StudentInfo(models.Model):
student_name = models.CharField("Student Name",max_length=20)
admission_date = models.DateField("Admission Date")
mobile_no1 = models.CharField("Mobile No.",max_length=12)
current_address = models.CharField("Current Address",max_length=20,blank=True)
batch_number = models.ForeignKey(BatchInfo)
coaching_id = models.IntegerField("Coaching ID")
def __unicode__(self):
return self.student_name
def __repr__(self):
return str(self.student_name)
And the other model BatchInfo that is related to StudentInfo
class BatchInfo(models.Model):
batch_name = models.CharField("Batch Name",max_length=20)
batch_started_from = models.DateField("Batch Started From")
no_of_registered_student = models.IntegerField("Number of Registered Student so far",default=0)
def __str__(self):
return self.batch_name
def __unicode__(self):
return self.batch_name
The strange part is that I've used the same style of code in other places which are perfectly functioning.
all_batch = BatchInfo.objects.all()
I try my best to solve it by my own but as a newbie, I found it very difficult for me. So I ask your help.
Thanks in advance.
So what I've learned so far about this problem is that there is no definitive answer exists for this particular type of problem. Django shows this error for multiple reasons. So I'm going to list all the scenarios and solutions that I've came across so far for this problem:
This problem might arise if you try to filter or access a field that does not exist in your model declaration.
Dirty Model Migration :P : As a beginner this was my nightmare. And most of the time I got this error for improper migration. So in case if you haven't migrated your model changes properly then you will get this error for sure. And to fix this problem you have to reset migration. To do this you can check the following link:
https://simpleisbetterthancomplex.com/tutorial/2016/07/26/how-to-reset-migrations.html
Note: I'll keep this answer updated once I get new scenario and their solution.
It looks like you are using Python 3.x
Change your
def __unicode__(self):
to
def __str__(self):
These problems arise when you have a problem with your DB.
Very excellent answer by #Shubho Shaha. I encounter the same problem and I debug it by following method.
class G(models.Model):
subscription_startdate = models.DateField(default=timezone.datetime.today().date())
...
...
I tried to access each field separately using .values and I found a problem with my DateField column because I assign wrong default value
I faced this problem due to bad variable naming. In my case:
class SomeModel(models.Model):
User = models.ForeignKey(User, .....)
# other fields ...
# .
# .
# .
The issue here is that I named the field user with capital 'U', i-e "User", which is actually the name of my django custom User Model, which, for some reason, django didn't like that and and got angry :p.
So I simply made the user field lower case, i-e :
user = models.ForeignKey(User, .....) # User --> user
This can happen when you do not specify the model name correctly in the serilizer. In my case this was the mistaken, and when i corrected it, it worked. here is an example;
model code
class ResourcesChosen(models.Model):
resources = models.ForeignKey(Resource, null=True, default=None, on_delete=models.CASCADE)
poll = models.ForeignKey(Polls, null=True, default=None, on_delete=models.CASCADE)
appusers = models.ForeignKey(AppUser, null=True, default=None, on_delete=models.CASCADE)
farmers = models.ForeignKey(Farmer, null=True, default=None, on_delete=models.CASCADE)
longitude = models.DecimalField(max_digits=11, decimal_places=7, null=True, blank=True)
latitude = models.DecimalField(max_digits=11, decimal_places=7, null=True, blank=True)
def __str__(self):
return self.resources
Serializer code
class ResourcesChosenSerializer(serializers.ModelSerializer):
class Meta:
model = Replies
fields = (
'id',
'resources'
'poll'
'appusers',
'farmers',
'latitude',
'longitude',
)
As you can see, the model name is different from what i specified in the model and that was causing issues. The correct way is;
class ResourcesChosenSerializer(serializers.ModelSerializer):
class Meta:
model = ResourcesChosen
fields = (
'id',
'resources'
'poll'
'appusers',
'farmers',
'latitude',
'longitude',
)
This fix eliminated the problem, "Unable to get repr for <class 'django.db.models.query.QuerySet'>" while retrieving data
My solution was simple.
class Report(TimestampedModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
report_id = models.CharField(max_length=255, blank=True, null=True)
sector = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.project_name
What caused my issue was that I was using a field (project_name) that was not part of the model fields. So I changed it to what was in the model and I stopped getting the error. .
def __str__(self):
return self.sector
This is how my problem got fixed.
Update
Another cause for the above issue as I found out here is that the returned data from the def str(self) method should be a string. Anything other than that will throw the above error.
A fix can be to convert the data type of what youre returning to a string like this;
def __str__(self):
return str(self.date_answered)

How to replace models.py in Django app in the production server

I have a simple django app that is using only the admin. This is the model as is now in the server:
from django.db import models
class School(models.Model):
school = models.CharField(max_length=200)
def __unicode__(self):
return self.school
class Lawyer(models.Model):
first = models.CharField(max_length=20)
initial = models.CharField(blank=True, max_length=2)
last = models.CharField(max_length=20)
year_graduated = models.IntegerField('Year graduated')
school = models.CharField(max_length=200)
school = models.ForeignKey(School)
class Meta:
ordering = ('last',)
def __unicode__(self):
return self.first
I want to add two new fields, so that the new models.py looks like this:
from django.db import models
class School(models.Model):
school = models.CharField(max_length=300)
def __unicode__(self):
return self.school
class Lawyer(models.Model):
firm_url = models.URLField('Bio', max_length=200)
firm_name = models.CharField('Firm', max_length=100)
first = models.CharField('First Name', max_length=50)
last = models.CharField('Last Name', max_length=50)
year_graduated = models.IntegerField('Year graduated')
school = models.CharField(max_length=300)
school = models.ForeignKey(School)
class Meta:
ordering = ('?',)
def __unicode__(self):
return self.first
Otherwise everything else is the same. Can I just upload this new models.py to the server and expect the application to work the same as before? I also need to clear what is in the database. I am using sqlite3.
I tried to deploy a new app but unfortunately the hosting co is refusing to help. Since I don't need two apps I thought about replacing models.py. This new app works in the django dev server as expected. I would appreciate advice since I will take care of the other outstanding questions after I make this app running. Thanks!
Edit
Thanks for all the answers. Since I want the database clear I will try jcd's solution. So, I will replace the old fields in the models.py
first = models.CharField(max_length=20)
initial = models.CharField(blank=True, max_length=2)
last = models.CharField(max_length=20)
year_graduated = models.IntegerField('Year graduated')
school = models.CharField(max_length=200)
school = models.ForeignKey(School)
with the new fields:
firm_url = models.URLField('Bio', max_length=200)
firm_name = models.CharField('Firm', max_length=100)
first = models.CharField('First Name', max_length=50)
last = models.CharField('Last Name', max_length=50)
year_graduated = models.IntegerField('Year graduated')
school = models.CharField(max_length=300)
school = models.ForeignKey(School)
to have
from django.db import models
class School(models.Model):
school = models.CharField(max_length=200)
def __unicode__(self):
return self.school
class Lawyer(models.Model):
firm_url = models.URLField('Bio', max_length=200)
firm_name = models.CharField('Firm', max_length=100)
first = models.CharField('First Name', max_length=50)
last = models.CharField('Last Name', max_length=50)
year_graduated = models.IntegerField('Year graduated')
school = models.CharField(max_length=300)
school = models.ForeignKey(School)
class Meta:
ordering = ('last',)
def __unicode__(self):
return self.first
and upload this to the server. Then I will run manage.py syncdb.
And when I open the page I will see the admin as it was before except with new fields.
I assume it is no problem to update the admin.py later to add the new fields:
class LawyerAdmin(admin.ModelAdmin):
fieldsets = [
('Name', {'fields': ['first', 'last', 'firm_name', 'firm_url']}),
('School', {'fields': ['school', 'year_graduated']}),
]
list_display = ('first', 'last', 'school', 'year_graduated', 'firm_name', 'firm_url')
list_filter = ['year_graduated']
#search_fields = ['last', 'first']
search_fields = ['school__school']
search_fields = ['school__lawyer__last']
Thanks again!
Since you're using a sqlite database, and you want to clear the data anyway, this is dead easy. Add your two fields, move your database to a backup location, and re-run manage.py syncdb. It will set up the new database for you. If you need to keep your old data, you are using a more complex database, or you want to manage your change over time, you should look into a schema migration tool like South.
No, you cannot just replace models.py.
You need some kind of schema migration.
If you don't use a tool like django south, you'll have to do it manually.
Look at http://www.sqlite.org/lang_altertable.html
You can use manage.py sqlall to see which SQL statements you need.
Run a manage.py sqlall on your project
This will dump the SQL create command
From there, look at the dump for your new columns, and use this to help create your Alter Table statements
Side note, is it kinda weird you have two "school" definitions?
Modifying a model on a live Django environment can be a bit of a hassle, depending on your approach.
If you don't mind losing data, a simple manage.py command will do the trick:
python manage.py reset [app name]
If, however, you want to retain the data that's already in the database, you'll have to execute some SQL manually to modify the schema. This can get messy to keep track of if you're not careful.
What I've done previously is to write a SQL statement for every change to any model, and record that somewhere along with the date. I also record the last time the schema was modified for any database (in my case, development, staging, and production). To update any one database to the correct schema, I just ran all the schema change SQL from dates after that particular database was last updated.
You can use python manage.py sqlall <appname> | grep <column name> to get the SQL definition of a particular column.
Then, you can do something like: ALTER TABLE my_table ADD COLUMN 'column_name' varchar(30);
(In this case, the manage.py line above returned 'column_name varchar(30);')

Categories

Resources