django giving cryptic error for foreignkey - python

I am getting this error for a django model:
ProgrammingError at /admin/notifications/eventtoken/
column notifications_eventtoken.user_id does not exist
LINE 1: ...ications_eventtoken" INNER JOIN "users_user" ON ( "notificat...
^
HINT: Perhaps you meant to reference the column "notifications_eventtoken.used_at".
I added a foreign key for user like this:
class EventToken(models.Model):
token = models.CharField(max_length=255, db_index=True)
user = models.ForeignKey(User, null=False, blank=False)
used_at = models.DateTimeField(null=True, blank=True)
event = models.ForeignKey(Event)
it works when I remove the user field, but breaks otherwise and I can't tell much from the error message.

It works when I remove the user field.
This is because your database is missing a column that you have programmed in your EventToken class which I'm guessing is inside of notifications/models.py. This is why it is called a ProgrammingError.
There are several ways to solve this:
1. Delete your entire database and sync it again! Not recommended for anything running on production, but for test projects really doesn't hurt much.
2. Use a tool like south or the django migrate app (depending on which django version you're using) to automate adding a table to your database using the manage.py script. Edit: this solution is the most viable as it's quick and adheres to DRY principles when working across multiple development environments.
3a. Manually go into your database using a command line tool and add the missing column. If I haven't made it clear... you're saying "I want to save the user_id" foreign key in this table" while your table is saying back "There is nowhere to save this ID." ...)
3b. Use a database GUI (like PGadmin for postgresql) and add the user_id column to your notifications_eventtoken database table.
4. Delete the user field in the EventToken class! Don't do this, but understand it works because it clears the logical discrepancy.

Related

How can I access to data stored in a ManyToMany related table in Django?

I want to make a query to obtain all the users that another user is "following" for a learning project.
When I execute the following python code:
user = User.objects.get(id=user_id)
followers = user.follows.all()
I don't get an error but instead I get a list with an object ( called Follow object (4) ) from which I can't access the user related properties.
I've checked this documentation here: https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/
But I can't find where I'm failing to use properly this type of model-relation.
Here are my Django models:
class User(AbstractUser):
pass
class Follow(models.Model):
user = models.ForeignKey(User, null=False, on_delete=models.CASCADE, related_name="follows")
follow = models.ManyToManyField(User, blank=True, related_name="followed_by")
I searched in my Django DB to see what is happening and I saw that there is a relational table called "network_follow_follow" that in fact has all the info that I need and is related with the object that I get from my Query, here are two pictures about the table that I can access and the one that I don't know how to access:
Table data requested by my code:
Table that I need to query:
So now I'm looking a way to access that last table, but to know how can I access straight forward to the last table data would be much better I think.
Thanks in advance.
See if this works for you.
follow_object = Follow.objects.filter(user=user)
followers_of_user = follow_object.follow.all()
I think the problem is that the user object does not have a user.follows function. You have created a seperate table in the database with that relationship data. I'm sure there's a better way of doing it but that's what I have done with something similar in my project.

Upgrade Django with incompatible migrations

I'm tasked with upgrading the Django version for a project that currently uses Django 2.2.24.
It contains a model (with existing migrations) that looks roughly like this:
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
type = models.ForeignKey(MembershipType, on_delete=None)
Starting with Django 3.0, on_delete=None causes an error since on_delete is supposed to be a callable. In order to avoid the error, both the model and the existing migrations have to be changed.
By itself, it's not an issue to change the model like this:
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
type = models.ForeignKey(MembershipType, on_delete=models.SET_NULL, null=True)
But existing databases are not yet aware that the corresponding field can be nullable, so a new migration is required for that.
The best way I currently see to do this is the following:
change the model
create&apply a migration using Django 2.2.24
change the old migrations manually
Is there a more elegant way to solve this issue?
I'm not sure this is the optimal solution, but maybe it will help you find a similar solution at least.
If you can reset the database, then you can find the migration file where the field was first created and change on_delete to SET_NULL and set null=True. Then remove the database and run migrations from scratch.
If you can't remove the database, then you could:
Change the model as your code.
Edit migration file where the field was created. (Same as above).
Manually in the database run the SQL to alter the field to make it nullable.

Django error when trying to migrate models with foreignkeys that don't have null=True or default set

I have this model that is a post like on Twitter, that has a creator. I'd ideally like the post to always require a creator_id and if the creator gets deleted then delete the post as well
class Post(AbstractBaseModel):
creator_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post_creator_id")
body = models.CharField(max_length=511)
Whenever I try to run 'python manage.py migrate' I get this error
"You are trying to change the nullable field 'creator_id' on cheerpost to non-nullable without a default; we can't do that (the database needs something to populate existing rows)."
The options to solve this are are 1) provide a one off default or 2) ignore for now. Neither of these seem to fulfill my constraint that I want to enforce, which is creator_id must exist and is the person who created the post or the entity gets deleted.
I've tried deleting the DB and recreating it from scratch in postgres as well as deleting it using the following query:
TRUNCATE Post;
DELETE FROM Post;
If you've deleted the DB, just the data and tables from DB are deleted.
That doesn't reflect any changes in Django. All the changes you've made to the fields of your model still exist in migrations. You have to delete the old migrations too.
Delete those old migrations from your app, create new migrations from scratch and apply them.
python manage.py makemigrations
python manage.py migrate
Django is asking you to provide a one-off default for any rows you already have in your database, since the field was nullable before the migration. The issue is that Django doesn’t know if there are any rows in the existing database where that column is null, so it needs instructions on what to do if it finds any. You can just provide one and forget about it—it will never be used again after the migration is complete.
Also, you may want to review how the related_name parameter works; you’ve got it backwards.

many to many table in django without using manytomanyfield

rather than using the models.ManyToMany field in django
i just set up a intermediary field with a bunch of foreign keys.
is there any reason why this wouldn't work. I can't think of any but why not see if any of you have tried the same.
class Authorization(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
permission = models.ForeignKey( 'venueadmin.Permissions', blank=True, null=True)
#venue = models.ForeignKey(venue) <-- commented out cause I haven't made the model its referencing yet.
That is exactly how ManyToMany relationships work, except few things to consider.
First, you might want to check how Django generates ManyToManyField here. It does almost the same you did here.
Now, before starting using separate model think about next things:
database constraint is missing. It means that there is no validation
on what has been put in to the Authorization table as example -
Duplicate rows;
there is no indexation which means that search will become slow once Authorization grows. Interesting enough I did not find it in Django, maybe nobody cares? Two columns table might not be so critical;
there is no reason to keep an authorization record for user with no permissions. What is the reason of setting permissions to NULL? Does it carry any useful information for DB administrator in future?

Django - syncdb doesn't create tables

I added a many-to-many field to an existing model and was expecting syncdb to create a new table, but there's nothing there. This is what the model looks like:
class Author(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self):
return "{0} {1}".format(self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
def __unicode__(self):
return self.title
Running sql myapp prints the correct statements with the new table, but this is not reflected when I run syncdb. validate also returns no errors. Does anyone know what could be the matter here? Or a better diagnostic?
The syncdb command does not create many to many tables for existing models by design. This decision is explained on ticket 2229.
That leaves you with a few options.
If you don't have any data in your Book model, drop the table and rerun syncdb. Django will recreate the book table and the many to many table.
Use the dbshell command, and create the many to many joining table using the output of sql myapp.
If you're doing multiple schema migrations with Django, make friends with South.
I found this explanation at the django docs useful: SchemaEvolution.
The de facto standard for database migration is Django South.
Its not perfect, but, it works pretty well. You should always check(and edit if necessary) your migration file before running it, to make sure that it actually does what it supposed to do.
You can check out their tutorial here.
Also, if you run:
python manage.py inspectdb > somefile.txt
You can get quickly check out if your database structure is matching your django models.

Categories

Resources