django get_or_create not working as expected - django

I have a model called snacks:
class Snack(models.Model):
snack = models.CharField(max_length=9)
When I do
Snack.objects.get_or_create(snack="borsh")
I get this error:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "restaurants_snack_pkey"
DETAIL: Key (id)=(6) already exists.
If I do it again, it's going to tell me the same thing except the key (that already exists) will be 7 and so on.
It's true that the key already exists, I'm wondering how can I make it pick a key that's the next one available?
Thanks in advance.
Jenia

You probably did some manual data importing, even if not, it's not problem with django, but with database auto increment sequence. Django has a management command that generates sql command to reset those:
./manage.py sqlsequencereset myapp1 myapp2
If you are using PostgreSQL you can just pipe it in like that:
./manage.py sqlsequencereset myapp1 myapp2 | psql
or mysql if you are using MySQL, but I haven't ried it.

Related

How do you use inspectdb in Django?

I am just starting with Django, and I would like to make an app that uses my existing sqlite db.
I read the docs and I found that you can create models from a db, using inspectdb; altho I can't find an example of how you use that command, on an existing db.
I copied the db file inside the directory of my project, ran the command and I see that a sqlite3 file is created in my directory project.
Altho the file has nothing to do with the database that I made. I tried to pass the db name to the inspectdb command but it says that it doesn't accept parameters.
So how can I actually tell the command to use my db to create the model for my app?
There must be some obvious step that I am missing...this is what I did:
-created the project
-created the app
-copied my db inside the project folder
-ran inspectdb
But I see the model empty, and a new db called db.sqlite3 created
Found the answer: there is a variable that has to be set, to define which one is the db that the application will use. the default is set to "db.sqlite3", which explain why I am getting this behavior.
Once you modify the name with the database that I already made, the command run without issues.
Not sure if it is just me getting stomped, but this info about the name that has to be changed was not mentioned anywhere...
Thanks

Django models.ForeignKey Foreign Key Constraint

I have the following 2 apps in my Django project. One app (player) has a ForeignKey that references the other app (team).
App 1 - players/models.py
class Player(models.Model):
name = models.CharField(max_length=100)
team = models.ForeignKey(Team)
App 2 - teams/models.py
class Team(models.Model):
name = models.CharField(max_length=100)
Problem #1 - Everything seems to work, but when I try to run manage.py reset teams I get the following error :
Error: Error: users couldn't be reset. Possible reasons:
* The database isn't running or isn't configured correctly.
* At least one of the database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlreset users'. That's the SQL this command wasn't able to run.
The full error: (1217, 'Cannot delete or update a parent row: a foreign key constraint fails')
I made sure all my tables are InnoDB. I've seen people suggest using SET FOREIGN_KEY_CHECKS=0 as a fix, but I'm not sure how to best use this with manage.py rest
Problem #2 - When I do a mysqldump, I cannot restore my MySQL db without running into errors. My basic procedure is as follows:
Dump my db.
mysqldump --user=root --password=pass --result-file=MYBACKUP.SQL --compact MYDB
DROP the database, and CREATE a new one with the same name.
Restore my db.
mysql -u root -p MYDB < MYBACKUP.SQL
And that's it. When I attempt to restore the first time, it gives me this error
ERROR 1005 (HY000) at line 12: Can't create table 'MYDB.auth_group_permissions' (errno: 150)
When I attempt to restore for the second (and subsequent) time, it makes it one line farther, but it gives me this error:
ERROR 1050 (42S01) at line 3: Table 'auth_group' already exists
I think those errors have to do with Foreign Key Constraints, but I'm not sure how to fix it.
I know this was a mouthful but any advice would be greatly appreciated. I'll post my findings here tomorrow, if any.
Thanks in advance!
Solution for Problem 2 - So my problem with dumping and then restoring my db has to do with how I use mysql dump - the --compact flag is causing the problem.
This line ...
mysqldump --user=root --password=pass --result-file=MYBACKUP.SQL --compact MYDB
... should be ...
mysqldump --user=root --password=pass --result-file=MYBACKUP.SQL MYDB

Django fixtures for permissions

I'm creating fixtures for permissions in Django. I'm able to get them loaded the way it's needed. However, my question is..say I want to load a fixture for the table auth_group_permissions, I need to specify a group_id and a permission_id, unfortunately fixtures aren't the best way to handle this. Is there an easier way to do this programmatically? So that I can get the id for particular values and have them filled in? How is this normally done?
As of at least Django >=1.7, it is now possible to store permissions in fixtures due to the introduction of "natural keys" as a serialization option.
You can read more about natural keys in the Django serialization documentation
The documentation explicitly mentions the use case for natural keys being when..
...objects are automatically created by Django during the database synchronization process, the primary key of a given relationship isn’t easy to predict; it will depend on how and when migrate was executed. This is true for all models which automatically generate objects, notably including Permission, Group, and User.
So for your specific question, regarding auth_group_permissions, you would dump your fixture using the following syntax:
python manage.py dumpdata auth --natural-foreign --natural-primary -e auth.Permission
The auth_permissions table must be explicitly excluded with the -e flag as that table is populated by the migrate command and will already have data prior to loading fixtures.
This fixture would then be loaded in the same way as any other fixtures
The proper solution is to create the permissions in the same manner the framework itself does.
You should connect to the built-in post_migrate signal either in the module management.py or management/__init__.py and create the permissions there. The documentation does say that any work performed in response to the post_migrate signal should not perform any database schema alterations, but you should also note that the framework itself creates the permissions in response to this signal.
So I'd suggest that you take a look at the management module of the django.contrib.auth application to see how it's supposed to be done.
Just to add to #jonpa's comment, if you are using multitenant app and you want to directly save the fixtures to a file you can do:
python manage.py tenant_command dumpdata --schema=<schema_name> --natural-foreign --natural-primary -e auth.Permission --indent 4 > /path/to/fixtures/fixtures.json

Django syncing Database Integrity Error

i was trying to deploy my application to heroku i was using sqlite so i have changed the settings to postgreSQL, i had some initial data initial_data.json then i removed it but i keep getting this error when i try to syncdb even without any initial data.
File /usr/local/lib/python2.6/site-packages/django/db/backends/postgresql_psycopg2/base.py, line 44, in execute
return self.cursor.execute(query, args)
django.db.utils.IntegrityError: duplicate key value violates unique constraint auth_permission_content_type_id_key
actually after looking i found that i have a permission i added customly that propably caused a conflict when i removed it it worked !!

South doesn't create default permissions on new models in time for latter migrations to use them

I'm not 100% sure I'm doing this right, but I think I've found an issue where auth.Permission objects aren't being created soon enough for migrations to use them when you initialize a DB from scratch.
The important details:
I'm trying to initialize a Django DB from scratch using ./manage.py syncdb --migrate --noinput
I have 11 migrations in my chain
The 1st migration creates a new model called myapp.CompanyAccount
The 9th migration tries to fetch the permission myapp.change_companyaccount with:
p = orm[ "auth.Permission" ].objects.get( codename = "change_companyaccount" )
At that point, an exception is raised:
django.contrib.auth.models.DoesNotExist: Permission matching query does not exist
I had assumed that the default permissions that are defined for every object (as per http://docs.djangoproject.com/en/dev/topics/auth/#default-permissions) would have been created by the time the 1st migration finished, but it doesn't appear that they are. If I re-run the migration after the exception, it works the second time because apparently the permission now exists and the 9th migration can execute without error.
Is there anything that can be done to "flush" everything sometime before the 9th migration runs so that the whole thing can run in a single pass without bailing out?
Thanks for any help / advice.
EDIT: In response to John's comment below, I found out that the following command-line sequence will work:
./manage.py syncdb (this initializes the default Django tables)
./manage.py migrate myapp 0001 (this causes the CompanyAccount table to be created)
./manage.py migrate myapp (this migrates all the way to the end without error)
Unfortunately, skipping step #2 above means that you get the same exception in the 0009 migration, which tells me that my original suspicion was correct that default permissions on new models are not created by South immediately, and are somehow only pushed into the database when the entire migration chain finishes.
This is better than where I was (I'm at least avoiding exceptions now) but I still need to manually segment the migration around the creation of new models that latter migrations might need to touch the permissions of, so this isn't a complete solution.
As it turns out, the answer is to manually call db.send_pending_create_signals() at some point before you try to access the default permission since South only does this "flushing" step quite late in the process. Thanks to Andrew Godwin from South for replying to this on the South mailing list here:
http://groups.google.com/group/south-users/browse_thread/thread/1de2219fe4f35959
Don't you have to run the default "syncdb" on a virgin database in order to create the South migration table; before you can use south. Are you doing that? It typically creates the permissions table at that time since you have django.contrib.auth in your INSTALLED_APPS.
http://south.aeracode.org/docs/installation.html#configuring-your-django-installation