question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Separate Class Files

See original GitHub issue

Sorry if this is a basic question with an obvious answer, I am relatively new to Python (long-time software engineer, just not with Python) and just attempting to use PonyORM.

I am building an application with quite a number of tables, relationships, and methods associated with the ORM classes. Due to this the model.py file I’m using, which started out just generated from the online editor, is getting rather large. My desire would be to separate each class into a separate class file under a “model” subdirectory within the project structure. However, since the relationships within the classes are dependent on one another this seems to setup a circular dependency which generates errors.

Is there any way to effectively separate out each class into a separate file given PonyORM relationships? I’ve put a very basic example below, not what I’m actually working on but easier to reference here, in this case having 4 separate class files (person.py, employee.py, contractor.py, and place.py) and potentially a master model.py file to load in the rest.

Any suggestions would be appreciated!

`from pony.orm import *

db = Database()

class Person(db.Entity): id = PrimaryKey(int, auto=True) name = Optional(str) email = Optional(str) phone = Optional(str) employee = Optional(‘Employee’) contractor = Optional(‘Contractor’)

class Employee(db.Entity): id = PrimaryKey(int, auto=True) employee_number = Optional(str) location = Optional(str) person = Required(Person) places = Set(‘Place’)

class Contractor(db.Entity): id = PrimaryKey(int, auto=True) contract_date = Optional(str) person = Required(Person)

class Place(db.Entity): id = PrimaryKey(int, auto=True) address = Optional(str) employees = Set(Employee)

db.generate_mapping()`

Thanks,

Chris

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
amalashkevichcommented, Jun 3, 2020

Thanks @stephancill I’m copying it here for the record.

You can use the following project structure:

# /myproject
#     settings.py
#     main.py
#     /models
#         __init__.py
#         base.py
#         requisitions.py
#         workorders.py
#         sales_orders.py

settings.py is a file with the database settings:

# settings.py
db_params = {'provider': 'sqlite', 'filename': ':memory:'}

main.py is a file with you application code. You put db.generate_mapping here:

# main.py
from pony import orm
import settings
from models import db
from your_favorite_web_framework import App

# orm.set_sql_degug(True)
db.bind(**settings.db_params)
db.generate_mapping(create_tables=True)

with orm.db_session:
    orm.select(u for u in db.User).show()

if __name__ == '__main__':
    app = App()
    app.run()

Note that it is not necessary to implicitly import all models, as they are accessible as attributes of the db object (e.g. db.User)

You can put the db object to base.py (or general.py), where you define your core models:

# base.py
from pony import orm

db = orm.Database()

class User(db.Entity):
    name = Required(str)
    orders = Set('Order')

Note that in the User model I can refer to the Order model defined in another module. You can also write it as

orders = Set(lambda: db.Order)

Unfortunately, IDEs like PyCharm at this moment cannot recognize that db.Order refers to the specific Order class. You can import and use the Order class directly, but in some cases it will lead to a cyclic imports problem.

In other model files you can import db from .base:

# workorders.py
from pony import orm
from .base import db

class Order(db.Entity):
    description = Optional(str)
    user = Required('User')

In the /models/__init__.py file you import all modules to ensure that all models classes are defined before the generate_mapping method is called:

# /models/__init__.py
from .base import db
from . import workorders
...

And then you can write

from models import db

And access models as db attributes like db.User, db.Order, etc.

If you want to refer models directly in your code instead of accessing them as the db attributes, you can import all models in __init__.py:

# /models/__init__.py
from .base import db, User
from .workorders import Order
...

And then you can import model classes this way:

from models import db, User, Order, ...
2reactions
RedPlatypuscommented, Jan 18, 2018

Mind posting a solution? I’m relatively new to Pony ORM and have come across a similar issue. In the past I would have something like this all in one file:

from pony.orm import *
class DBConnector:
  # on initialization, open db, and define our entities in class
  def __init__(self):
    self._open_database()
    self._define_entities()
    self.db.generate_mappings(create_tables=True)

  def._open_database(self):
    # open the database, mysql, sqlite, oracle, whatever
    self.db = Database()
    self.db.bind(...)

This is the part I’m trying to fix/ do better/ move to its own file: The more tables I have, the more bloated my database class becomes but so far I haven’t found a good any way to separate the entities from the DBConnector class.

  def._define_entities(self):
    class Person(self.db.Entity):
      name = Required(str)
      age = Required(int)
      cars = set('Car')

    class SecondTable(self.db.Entity):
      columnone = Required(str)

    class NthTable(self.db.Entity):
      ...

The rest of the class is your usual

  def.get_people(self):
    return self.db("Query here")

Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Separate classes into separate files in C++ - Stack Overflow
Separate classes into separate files in C++ · Create new class, and CB gives you a ".h" and a new ". · The...
Read more >
Chapter 7: Placing class code in separate files
Using your class in main and other classes​​ In any file where you want to use your class, just include its header file....
Read more >
C++ Separate Header and Implementation Files
C++ classes (and often function prototypes) are normally split up into two files. The header file has the extension of .h and contains...
Read more >
Exercise 3: Defining Objects in Separate Files - Graham Mitchell
Type up the following code, and put each class into its own file, named as shown. Save them all in the same folder....
Read more >
Methods in Separate Files - MATLAB & Simulink - MathWorks
To define a method in a separate file in the class folder, create the function in a file. Do not use the method...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found