Django : loaddata to update data
Asked Answered
M

2

15

I have a fixture seed_data.json on which I have my initial data.

Sometimes I add new data into this fixtures and reload it, which updates my data correctly.

However, I now want to remove some data from it. So I modified my seed_data.json, for instance, I had something like that :

{"fields": {"name": "Field 0"},"model": "catalog.product","pk": 1},
{"fields": {"name": "Field 1"},"model": "catalog.product","pk": 2},
{"fields": {"name": "Field 2"},"model": "catalog.product","pk": 3},
# ...

That became :

{"fields": {"name": "Field 1"},"model": "catalog.product","pk": 1},
{"fields": {"name": "Field 2"},"model": "catalog.product","pk": 2},
# ...

But I'm getting :

django.db.utils.IntegrityError: Problem installing fixture .....\seed_data.json

Could not load catalog.Product(pk=2): column name is not unique

So there's no problem when adding some data, but when trying to remove some, there are conflicts with the primary keys.

How can I achieve what I'm trying to do ?

Macmullin answered 29/1, 2016 at 16:53 Comment(0)
D
8

Getting there after all those years and with an unresolved question makes me want to add something because I did struggle with fixtures too.

For modifying existing data, as @Thomas said the best it to use Django data migrations.

When new to Django though, you might be tempted to use fixtures for updating some basic data. Again, this is not recommended but it doesn't hurt to explain what can be done. So, using the example:

{"fields": {"name": "Field 0"},"model": "catalog.product","pk": 1},
{"fields": {"name": "Field 1"},"model": "catalog.product","pk": 2},
{"fields": {"name": "Field 2"},"model": "catalog.product","pk": 3},
# ...

That became :

{"fields": {"name": "Field 1"},"model": "catalog.product","pk": 1},
{"fields": {"name": "Field 2"},"model": "catalog.product","pk": 2},
# ...

Here, the issue is indeed to try to update an object with a primary key that already exists on another object (object with pk = 3). You cannot delete the object with pk = 3 just with the fixture. If you do it manually though, then the updated fixture above would have worked.

Here are some rules that can help.

What you can do when modifying a fixture and calling loaddata on it:

  • Update data (as long as it respects unicity constraints). Django will use pk to match object and will replace the previous object without calling any pre_save functions (so that's another reason why it's not recommended to use it)
  • Create data (with the same constraints as before)

What you cannot do when modifying a fixture and calling loaddata on it:

  • You cannot explicitly delete an object with a fixture. As the pk of the object you want to delete won't be in the file, it will stay as is in the database. So you have to delete it manually.
Donatelli answered 21/4, 2021 at 17:13 Comment(0)
M
5

Fixtures are only for initial data for completely new database instances, e g when running tests. To modify existing data use migrations.

Madelon answered 29/1, 2016 at 20:28 Comment(6)
SO, in order to actually change the initial data of the application, I need to wipe my database ?Macmullin
Yea, but, sometimes if we update an application, there is some changes to the initial data. And wiping the database will also remove data that aren't initial. Sure I can use the admin interface, But I wanted to keep clean primary key on recordsMacmullin
No you don't use the admin. You write a data migration, like I said.Madelon
Well, I thought migrations were made for changes in models or so. I'll look into data migrations.Macmullin
No, it's only for the schema of the table, like @Macmullin wrote. You can't update the data inside with that.Procne
@Procne not true, please read the docs to understand how migrations help with migrating data in addition to schema docs.djangoproject.com/en/3.2/howto/writing-migrationsVantassel

© 2022 - 2024 — McMap. All rights reserved.