Skip to content
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

Use peewee-moves for database migrations #62

Merged
merged 5 commits into from
Feb 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


## Unreleased
+ Implemented database migrations (#62)
+ Changed (again) how we handle being behind a proxy. (#60)


Expand Down
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,86 @@ This is handled in CI, but in case you need to do it manually:
docker build -f docker/Dockerfile -t trendlines:latest -t dougthor42/trendlines:latest .
docker push dougthor42/trendlines:latest
```


### Database Migrations

This project uses [`peewee-moves`](https://github.com/timster/peewee-moves)
to handle migrations. The documentation for that project is a little lacking,
but I found it a litte easier to use than the more-popular
[`peewee-migrate`](https://github.com/klen/peewee_migrate). `peewee-moves`
also has more documentation.

To apply migrations to an exsiting database that has ***never had any
migrations applied***:

1. Open up the database
2. Manually create the following table (adjust syntax accordingly):
```sql
CREATE TABLE migration_history (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`date_applied` DATETIME NOT NULL,
PRIMARY_KEY (`id`));
```
3. Populate the table with all the migrations that have already been
applied. The `name` value should match the migration filename, sans `.py`
extension, and the `date_applied` field can be any timestamp.
```sql
INSERT INTO `migration_history`
(`name`, `date_applied`)
VALUES
('0001_create_table_metric', '2019-02-14 14:56:37'),
('0002_create_table_datapoint', '2019-02-14 14:56:37');
```
4. Verify that things are working. You should see `[x]` for all migrations:
```shell
peewee-db --directory migrations --database sqlite:///internal.db status
```


#### Creating a new Table

1. Create the table in `trendlines.orm`.
2. Create the new table migration:
```shell
$ peewee-db --directory migrations \
--database sqlite:///internal.db \
create \
trendlines.orm.NewTable
```
3. And then apply it:
```shell
$ peewee-db --directory migrations \
--database sqlite:///internal.db \
upgrade
```

If you're using the python shell, run the following for for step 3:
```python
>>> from peewee import SqliteDatabase
>>> from peewee_moves import DatabaseManager
>>> manager = DatabaseManager(SqliteDatabase('internal.db')
>>> manager.create('trendlines.orm')
>>> manager.upgrade()
```


#### Modifying a table:

1. Modify the table in `trendlines.orm`.
2. Create the migration file:
```shell
$ peewee-db --directory migrations \
--database sqlite:///internal.db \
revision
"short_revision_description spaces OK but not recommended"
```
3. Manually modify the `upgrade` and `downgrade` scripts in the new
migration file.
4. Apply the migration:
```shell
$ peewee-db --directory migrations \
--database sqlite:///internal.db \
upgrade
```
15 changes: 15 additions & 0 deletions migrations/0001_create_table_metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""
create table metric
date created: 2019-02-14 22:01:44.111130
"""


def upgrade(migrator):
with migrator.create_table('metric') as table:
table.int('metric_id')
table.char('name', max_length=120)
table.char('units', max_length=24, null=True)


def downgrade(migrator):
migrator.drop_table('metric')
16 changes: 16 additions & 0 deletions migrations/0002_create_table_datapoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
create table datapoint
date created: 2019-02-14 22:01:50.586924
"""


def upgrade(migrator):
with migrator.create_table('datapoint') as table:
table.int('datapoint_id')
table.foreign_key('INT', 'metric_id', on_delete=None, on_update=None, references='metric.metric_id')
table.float('value')
table.int('timestamp')


def downgrade(migrator):
migrator.drop_table('datapoint')
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ flask==1.0.2
peewee==3.8.0
requests==2.21.0
celery[redis]==4.2.1
peewee-moves==2.0.0
15 changes: 9 additions & 6 deletions src/trendlines/orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,30 @@
db = SqliteDatabase(None)


class DataModel(Model):
class BaseModel(Model):
class Meta(object):
database = db


class DataModel(BaseModel):
"""
Model for storing data points.

I've kept this broken out into a separate class because there may be
a point in the future where I want to switch to one-file-per-metric
and having a separate DataModel class will make this easier.
"""
class Meta(object):
database = db
pass


class InternalModel(Model):
class InternalModel(BaseModel):
"""
Model for internal data tables.

*IF* we were to move to one-file-per-metric, then this model would
hold all of the non-dynamically-generated tables.
"""
class Meta(object):
database = db
pass


class Metric(InternalModel):
Expand Down