def forward(migrator): # Add a placeholder field for storing a link to a WebPageContent object migrate( migrator.add_column( "searchresultcontent", "webpagecontent_id", ForeignKeyField(WebPageContent, null=True, to_field=WebPageContent.id), ) ) # Move the data previously in SearchResultContent model into WebPageContent, # and link the WebPageContent to the SearchResultContent. # Note that because the model for SearchResultContent has already been updated beyond the # state of the table, we have to access the 'content' and 'date' fields through the "SQL" # class instead of a field on the model. This is also the reason that we mix both # Query object methods and raw queries below. The models access the future field names, # and the raw queries access the past field names. content_records = ( SearchResultContent.select(SQL("content"), SQL("date"), SearchResult.url, SearchResultContent.id) .join(SearchResult) .dicts() ) for record in content_records: web_page_content = WebPageContent.create(content=record["content"], date=record["date"], url=record["url"]) # Normally, it's not recommended to directly insert values into queries. But I do # it here because I think Postgres and SQLite have two different interpolating strings, # so this is one way to write the migration to make it more portable. # I also think there is no risk that either of these fields that I insert will # be anything other than an integer. SearchResultContent.raw( "UPDATE searchresultcontent SET webpagecontent_id = " + str(web_page_content.id) + "WHERE id = " + str(record["id"]) ).execute() # Drop unnecessary columns from SearchResultContent model migrate( migrator.drop_column("searchresultcontent", "date"), migrator.drop_column("searchresultcontent", "content"), migrator.rename_column("searchresultcontent", "webpagecontent_id", "content_id"), migrator.drop_not_null("searchresultcontent", "content_id"), )