Run1e
Run1e

Reputation: 11

Update model with newly added field/column

Python app, using peewee to work with SQLite databases.

I have this model containing one field:

class RepUser(Model):
    user = BigIntegerField()

And I update the database schema using a migrator like this:

new_field = IntegerField(null=True)
migrate(migrator.add_column('repuser', 'abc', new_field))

I expected that the model would update its fields to accomodate for the extra field being inserted, but it does not.

For example, this gives a KeyError:

model_instance.abc = 42

The goal is to be able to dynamically add and remove fields, and have the model update so they can be used.

I found a related question here: Update existing table/model column/fields?

The top answer says the model has to be updated as well after adding fields to the database schema, but I am not sure how to do this, and I can't find related information in the documentation.

Thanks in advance for any help.

Upvotes: 0

Views: 1024

Answers (2)

coleifer
coleifer

Reputation: 26235

In 3.0a you'll use the Model._meta.add_field() method instead:

class User(Model):
    pass

f = TextField()
User._meta.add_field('username', f)

print(User._meta.fields)
# {'id': <peewee.AutoField at 0x7f552815bc50>,
#  'username': <peewee.TextField at 0x7f552b1d7e10>}

Upvotes: 0

Run1e
Run1e

Reputation: 11

I found a solution, in case someone stumbles upon this in the future.

The Field base class has an instance method called add_to_class, which does exactly what I wanted.

So you can do

new_field = SomeField()
new_field.add_to_class(model_class, 'column_name')

Note that when you connect to your database, you'll have to get all the columns and add them to your model base manually. I do this right after I connect to the database:

for index, column_name in enumerate(database.get_columns('table_name')):
    if (index < 2): # 2 is in my case how many columns I have that are 'static'
        continue
    new_field = SomeField()
    new_field.add_to_class(table_name, column_name)

Obviously you'll have to change specifics.

There is no mention of this in the documentation afaik. I literally had to look at the source to find this method.

Sorry if my terminology is a bit wrong, I'm relatively new to python.

Upvotes: 1

Related Questions