-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PageChooserBlock/ImageChooserBlock values go null when restoring from loaddata #2218
Comments
I suspect this happens at the point where A possible fix would be to make StreamBlock.get_prep_value aware of lazy StreamValues, to avoid the round trip:
|
Check how can we solve it, as I also have this issue. |
Currently lazy StreamFields contain initial JSON data read from the database. When written back to the database, instead of reusing the JSON, it is first converted to Python objects and then converted back to JSON. This not only potentially introduces extraneous database queries but also makes it more difficult for developers to access the raw JSON for e.g. migrations. This change fixes wagtail#2218 where using loaddata to load PageChooserBlock/ImageChooserBlock values in a StreamField may lead to broken references. To verify, follow the instructions in that issue to create a data dump with a page and images, then edit the dump so that the page is loaded before the image. You'll see that page-image references are properly loaded even if the dump order isn't in dependency order. This change includes some slight changes to two API unit tests to get them to pass. In those tests we manually create StreamField data without providing an ID. The test was checking to see that the data retrieved from the API did contain an ID, because the previous logic would add one during the JSON->Python->JSON round trip. This change removes that roundtrip and so the test needs to provide an ID in the test data. Unfortunately this does mean that if anyone is using a similar mechanism to create StreamField data manually, and counting on IDs being added automatically even if they are never accessed outside of the API, this will break. As this kind of creation is unsupported I wasn't sure if I should add some kind of logic to handle this; one potential place to do that would be in wagtail.api.v2.serializers.StreamField: if the field is lazy, make sure that it's fully realized as bound blocks before returning the API representation.
Currently lazy StreamFields contain initial JSON data read from the database. When written back to the database, instead of reusing the JSON, it is first converted to Python objects and then converted back to JSON. This not only potentially introduces extraneous database queries but also makes it more difficult for developers to access the raw JSON for e.g. migrations. This change fixes wagtail#2218 where using loaddata to load PageChooserBlock/ImageChooserBlock values in a StreamField may lead to broken references. To verify, follow the instructions in that issue to create a data dump with a page and images, then edit the dump so that the page is loaded before the image. You'll see that page-image references are properly loaded even if the dump order isn't in dependency order. This change includes some slight changes to two API unit tests to get them to pass. In those tests we manually create StreamField data without providing an ID. The test was checking to see that the data retrieved from the API did contain an ID, because the previous logic would add one during the JSON->Python->JSON round trip. This change removes that roundtrip and so the test needs to provide an ID in the test data. Unfortunately this does mean that if anyone is using a similar mechanism to create StreamField data manually, and counting on IDs being added automatically even if they are never accessed outside of the API, this will break. As this kind of creation is unsupported I wasn't sure if I should add some kind of logic to handle this; one potential place to do that would be in wagtail.api.v2.serializers.StreamField: if the field is lazy, make sure that it's fully realized as bound blocks before returning the API representation.
If a database dump is taken using
./manage.py dumpdata > data.json
, and then restored to an empty database (after taking care of #2217) using./manage.py loaddata data.json
, StreamField chooser blocks can loose their value.This behaviour is dependent upon the order of the data from
dumpdata
, so is not 100% reproducible without some manual intervention. It does happen without manual intervention on occasion though.My best guess is that StreamFields will validate their data for validity and integrity when they are unserialized. If the page instance a PageChooserBlock references, or the image an ImageChooserBlock references has not been loaded yet, the StreamField will replace the instance ID with null. When the
loaddata
import is finished, the database is not how it should be, and any ChooserBlocks that were loaded in the wrong order will be empty.To reproduce:
wagtail start testdata
Add a StreamField with some chooser blocks to the HomePage:
./manage.py makemigrations
;./manage.py migrate
Edit the HomePage from the admin, choosing some pages and images in the StreamField.
Dump, flush and load the data:
Go back to the admin, or use
./manage.py dbshell
, to observe that HomePage.body no longer correctly references the chosen pages and images. Instead, these chooser blocks are blank as if nothing has been chosen, withnull
in the fields instead of the page/image id.As mentioned, this behaviour is dependant upon the order of the data dump, which is not consistent across runs. You can manually ensure the incorrect behaviour happens by editing
data.json
and moving theHomePage
instances above the pages/images referenced in the StreamField. The rest of the data loading will work, including foreign keys to instances yet to be created.The text was updated successfully, but these errors were encountered: