I'm working on creating a filter in django where the options displayed are coming from a new column in the database. It turns out that this column was created directly in the database and so that it could be displayed in my template, I need to capture this field in the models.
After some research, I found in django's own documentation a function called "inspectdb" that is called by manage.py. So far so good, after executing the function, the database fields are added to my project so that they can be directed to their corresponding app.models.
The documentation indicates that I must perform a python manage.py migrate for the sync to complete, this snippet of code is where the problem happens. When performing the migrate, I get the following error: "django.db.utils.ProgrammingError: relation "crontabmanager" already exists"
The "crontabmanager" table actually exists in my database, but it is not changing at this time.
Some actions were taken to try to get around this problem, for example:
I tried to ignore the migration and use the new field directly in the system, but it returns stating that the new column does not exist
Delete the migration file and create a new "makemigration"
Delete the "crontabmanager" table from the database for django to recreate through the ORM
Changing models.py properties to ignore changes made
Below is the snippet of my current models.py code:
from django.db import models
class Crontab(models.Model):
client = models.TextField('Cliente', blank=True, null=True)
script = models.TextField('Nome do script', primary_key=True)
schedule_code = models.TextField('Codigo Crontab', blank=True, null=True)
crontab_command = models.TextField("Comando", blank=True, null=True)
log = models.TextField("Log", blank=True, null=True)
class Meta:
verbose_name = 'Crontab'
verbose_name_plural = 'Crontab'
db_table = "crontabmanager"
class Trello(models.Model):
id_card = models.TextField('ID do Card', primary_key=True)
card_name = models.TextField('Nome do Card', blank=True, null=True)
due_date = models.TextField('Data de conclusão', blank=True, null=True)
list_name = models.TextField('Nome da lista', blank=True, null=True)
tipo_corte = models.TextField('Tipo do corte', blank=True, null=True)
cortes = models.TextField('Numero de cortes', blank=True, null=True)
unidade = models.CharField(max_length=200, blank=True, null=True) #new field added
class Meta:
db_table = "trello_pta"
error when running python manage.py migrate
$ python3 manage.py migrate
Operations to perform:
Apply all migrations: accounts, admin, auth, contenttypes, core, sessions, users
Running migrations:
Applying core.0002_initial...Traceback (most recent call last):
File "/home/file_names/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 87, in _execute
return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "crontabmanager" already exists
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
...
return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "crontabmanager" already exists
AttributeError: Got AttributeError when attempting to get a value for field vesting_choice_id on serializer VestingLocationRateSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
Original exception text was: 'QuerySet' object has no attribute 'vesting_choice_id'.
Model
class VestingChoice(models.Model):
id = UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
participant = ForeignKey('Participant', on_delete=CASCADE, related_name="participants_id")
vesting = ForeignKey('Vesting', on_delete=CASCADE, related_name="vestings")
class VestingLocationRate(models.Model):
id = UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
vesting_choice_id = ForeignKey('VestingChoice', on_delete=CASCADE,
related_name="vesting_choice")
country_id = ForeignKey(Country, on_delete=CASCADE, related_name="country_id")
Serializers
class VestingChoiceSerializer(serializers.ModelSerializer):
class Meta:
model = VestingChoice
fields = "__all__"
class VestingLocationRateSerializer(serializers.ModelSerializer):
vesting_choice_id = VestingChoiceSerializer(many = False)
country_id = CountrySerializer(many = False)
class Meta:
model = VestingLocationRate
fields = "__all__"
In vesting_choice_id on_delete=models.CASCADE not on_delete=CASCADE
And seems like you haven't migrate after adding vesting_choice_id,
so try to run python manage.py makemigrations then python manage.py migrate
If you're trying to fetch multiple instances of your model, make sure that in your view function, at the serialization level, you have set many to True
Something like this
models = YourModel.objects.all()
serializer = YourModelSerializer(models, many=True)
return JsonResponse(serializer.data, safe=False)
This is a 2 problem post, which i suspect are somehow connected.
My posts app on Django doesn't migrate properly (I think), and adding the 'author' (Users AbstractUser model) breaks my code with the error:
str returned non-string (type tuple)
whenever I try to add a row.
I changed the name of the table using db_table (so it will change Postss to Posts on the admin page) and added an output to the __str__ function, I tried a few variations of output for the str function but non of them worked. I even tried to comment it out. and still. no changes in the table name or the error. I tried changing my str functions a few times and got the same result. when deleting the str function, I still get that same result.
I have a few wild guesses about this situation:
it might not work with an abstract users class for some reason, and do not know to to work around this and why this happens at all. (removeing the author=... row resolves this problem but doesn't change the table name, but I do need the user fk there).
it might not be migrating properly due to my environment or python version Python 3.9.1(?).
PS: every change I have made included stopping the server from running and running the lines: python manage.py migrate and python manage.py makemigrations.
posts/models.py:
from django.db import models
from users.models import Users
class Posts(models.Model):
content = models.TextField(max_length=255)
author = models.ForeignKey('users.Users', on_delete=models.CASCADE, null=True)
timestamp = models.DateTimeField(auto_now_add=True, null=True)
class Meta:
db_table = 'Posts'
def __str__(self):
return self.content + " " + self.author.email + " " + self.timestamp
I will add my users model too:
from django.db import models
from django.contrib.auth.models import AbstractUser
# https://rahmanfadhil.com/django-login-with-email/
class Users(AbstractUser):
USERNAME_FIELD = 'email'
email = models.EmailField(unique=True)
REQUIRED_FIELDS = ['username'] # removes email from REQUIRED_FIELDS
def __str__(self):
return (self.email, self.username)
You are trying return a tuple, it must be a string.
def str(self):
return (self.email, self.username)
Use the new-style formatting in Python
Try this instead:
class Users(AbstractUser):
...
def __str__(self):
template = '{0.email} {0.username}'
return template.format(self)
class Posts(models.Model):
...
def __str__(self):
template = '{0.content} {0.author.email} {0.timestamp}'
return template.format(self)
or
def __str__(self):
return '{} {} {}'.format(self.content, self.author.email, self.timestamp)
Second Question:
If I understand your question correctly, then to change the label for the model, you need to use verbose_name:
class Meta:
verbose_name = 'Post'
verbose_name_plural = 'Posts'
With option db_table you change the name of the database table to use for the model.
And see explanation how it works, from Django: if you have an app bookstore (as created by manage.py startapp bookstore), a model defined as class Book will have a database table named bookstore_book.
Then db_table must be:
class Meta:
# your desired table name can you find in your database
db_table = 'appLabel_modelName'
To list the tables in the current database for PostgreSQL, you can run:
python manage.py dbshell
\dt
See also Django db_table
Try changing your __str__ method to this:
def __str__(self):
return self.content + " " + str(self.author.email) + " " + str(self.timestamp)
Also, you only need to migrate when you've made changes to the models not model methods.
I am using Django 1.11 and typed below codes in models.py. It works fine when makemigrations, but it notices the error of "models.DoesNotExist" when do migrate.
The code in models.py:
class RecordType(models.Model):
name = models.CharField(max_length=100, default='out',blank=True, verbose_name="name")
def get_record_type_default():
return RecordType.objects.get_or_create(pk=1)[0].id
class PrimaryCategory(models.Model):
type = models.ForeignKey(RecordType, on_delete=models.PROTECT, default=get_record_type_default, verbose_name="type")
def get_primary_category_default():
return PrimaryCategory.objects.get_or_create(pk=1)[0].id
class SecondaryCategory(models.Model):
primary_category = models.ForeignKey(PrimaryCategory, on_delete=models.PROTECT, default=get_primary_category_default, verbose_name="1st category")
def get_secondary_category_default():
return SecondaryCategory.objects.get_or_create(pk=1)[0].id
class Record(models.Model):
secondary_category = models.ForeignKey(SecondaryCategory, on_delete=models.PROTECT, default=get_secondary_category_default, verbose_name="2nd category")
And here is the error message while doing migrate:
File "C:\Users\myname\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 464, in get_or_create
return self.get(**lookup), False
File "C:\Users\myname\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 380, in get
self.model._meta.object_name
datacore.models.DoesNotExist: SecondaryCategory matching query does not exist.
you can use following way to create object:
get_object_or_404(RecordType, pk=id)
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()