-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Best practices: how to manage classes that may or may not have database data #2897
Comments
In my (small compared to yours) experience, I've always used only one class and used class methods, methods and properties to achieve whatever I wanted. That way my peewee class can do stuff not necessarily related to the database if not required (though I don't have an example on hand right now) |
Thanks for your answer.
(where |
Some random (untested) code I quickly wrote that you could definitely do: from peewee import ModelBase, CharField, AutoField, IntegerField
class Project(ModelBase):
id = AutoField()
name = CharField(null=True)
description = CharField(null=True)
status = IntegerField(null=True)
class Meta:
table_name = 'project'
def do_something(self):
# You can have access to the database columns through here
print(self.id)
def do_something_else(self):
# Same deal here
print(self.name)
def if_something(self):
# You can also do some logic here
return self.status == 1
def upsert(cls, **kwargs):
try:
return cls.get(cls.id == kwargs['id'])
except cls.DoesNotExist:
return cls.create(**kwargs) Keep in mind that creating a |
My opinion is that it is almost always best to just use one class to represent the entity (whether it be a user, a project, whatever). If there is a significant amount of business logic, I will then write a higher-level class that orchestrates the various model classes -- but this is typically a singleton-type class. For example in scout, a search server, we have the various model classes with helper methods here and then a higher-level "search" class and view classes to implement the coordination and business logic: https://github.com/coleifer/scout/blob/master/scout/search.py and https://github.com/coleifer/scout/blob/master/scout/views.py |
I looked at the classes with helper methods, and those classes are all intended to be used only when dealing with the database. They do not represent a
But what happens in a more generic application, where the lifecycle of a document can happen (1) entirely with, (2) entirely without, or (3) start without and end with a database interaction? For example I could:
My My current and ugly solution is with two classes A Soo... I know I can create a # create an instance without touching the database
p = Project('xyz')
if p.that_file_exists():
# only now start interacting with the database
p.get()
p.update_with_file_content()
p.save() |
If the database is the ultimate source of truth for that object then it makes sense to me to use the model instance as the way of working with that object -- whether or not you "save" it or anything like that. |
I think my point is that the database is not the ultimate source of truth. In my example some of the truth is in the file system, and an instance of I would like to be able to get the same object whether I do I am wondering if a class derived from The methods Right now I have two classes:
But with this implementation it is not clear who is in charge and ugly things happen. |
Well, quod scripsi scripsi |
Thank you. I will resist the temptation to refactor this old project and keep it ugly. I guess my use case is uncommon, and the answer to the subject is "Peewee classes deal with databases. You can add all the logic you like, but the Peewee classes still deal with databases". |
It’s all python, they’re just classes. |
After a long time, I am working on a 10+ year old application that uses
Peewee
, and I have noticed that I had created two classesProject
andDbProject
. Both classes represent the same object, butProject
manages things about a project that don't need to know anything about the info stored in the database, whileDbProject
is derived frompeewee.Model
.Now I am wondering if that was young me doing the wrong thing, or if this is old me trying to oversimplify.
It sure feels wrong to have two classes to represent the same thing. My instinct today would be to have one class that can be used either with or without database interaction, but at the same time I'm not sure I can use classes derived from
model.Peewee
to do stuff that has nothing to do with the database.For example,
Project
can build a list of pathnames based on the project number, and make decisions based on that, without requiring access to the database. Something like this:Here
Project.get_db_entry
manages caching and upsert.The problem with this solution is that, for example, when I get a
DbProject
with something likedb_p = client.db_project
, I can't dodb_p.production_package_files()
.What is the best way to have a
Project
class that can do everything a project needs, whether it's related to the database or not?The text was updated successfully, but these errors were encountered: