Search code examples
pythonsqliteormpylintpeewee

How to dynamically set SQLite database file path using Peewee in production and testing?


I'm developing a Python application to be run in local with a SQLite database using Peewee as ORM. I have automated testing (test.py) for development connecting to a designated SQLite database and in production I want to have the ability to dynamically set the path to the production database - I need to be dynamic to connect to multiple databases. I'm planning on running application from main.py for production and from test.py for testing.

Each model sets the model class database connection in the class meta.

At run time, either in testing or in production, is there a way to set the value of the the db variable so that it can be used to correctly connect to the database whenever there is an instance of each model class instantiated?

#main.py

from models import (
    ExampleModel,
    db,
    )


def main():

    #request user input on database filepath

    db.init(raw_input('Enter path to database'))

    exampleObj = ExampleModel.select().where(ExampleModel.id == 1).get()


if __name__ == '__main__':
    main()


#models.py

from peewee import *

db = SqliteDatabase(None)


class ExampleModel(Model):

    field1 = IntegerField(null=True)
    field2 = TextField(null=True)
    updateDate = DateTimeField(default=datetime.datetime.now)

    class Meta:
        database = db
        db_table = 'ExampleModel'


#test.py

import unittest
from models import (
    ExampleModel,
    db,
    )


class testSetUp(unittest.TestCase):

    def test_ExampleModelConnection(self):

        db.init(r'C:\path\to\file')

        exampleObj = ExampleModel.select().where(ExampleModel.id == 1).get()

        self.assertEqual(exampleObj.id, 1)

Solution

  • global is not an operator in the sense you're trying to use it. It's strange, but you would write instead:

    global db
    database = db
    

    There's a problem with your code, however. You're attempting to use a string for the Model.Meta.database attribute -- this attribute should be a database instance:

    db = SqliteDatabase('some-file.db')
    
    class MyModel(Model):
        class Meta:
            database = db
    

    To defer initialization, you can do this:

    db = SqliteDatabase(None)
    
    class MyModel(Model):
        class Meta:
            database = db
    
    # later...
    if IS_TESTING:
        db.init('testing.db')
    else:
        db.init('production.db')
    

    Docs: http://docs.peewee-orm.com/en/latest/peewee/database.html#run-time-database-configuration