-1

I'm trying to assign a class name dynamically using a string.

Much like this...

classname='cats'

class classname(peewee.Model):

Peewee doesn't seem to think I should be able to do this and I'm having a lot of trouble finding a way to define the class name dynamically.

Help!

Byron Hill
  • 11
  • 1
  • 6
  • 1
    Why do you need to define the classname dynamically? That's super weird. – coleifer Sep 13 '14 at 20:56
  • The database contains a list of device functions and their respective values. The application at hand is a server, it receives strings from a control device. the string contains the device type, the command and the value. The intention is that when the server recieves the string, it extracts the devicetype from it and then uses that to interact with the correct part of the database. It is not possible in this case for a simple if (devicetype = device): argument to be used because additional device types may be added later – Byron Hill Sep 14 '14 at 06:31
  • Why not just add a devicetype column, instead of dynamically creating a table for it? – coleifer Sep 15 '14 at 15:11

3 Answers3

13

If you need to control the table name, you can do:

 class MyModel(Model):
     whatever = CharField()

     class Meta:
         db_table = 'my_table_name'
coleifer
  • 24,887
  • 6
  • 60
  • 75
  • Note: for anyone reading this lately and using a recent version of Peewee, the `db_table` attribute above has now changed to `table_name`. – QA Collective Oct 15 '20 at 11:31
2

I have a same problem with you,and find a solution at last. Maybe it's not a good idea to Dynamically define name of class in peewee model.

class Person(Model):
    name = CharField()
    birthday = DateField()
    is_relative = BooleanField()

    class Meta:
        database = db
        db_table = "Hello"

>>> Person.__dict__
mappingproxy({'DoesNotExist': <class 'peewee.PersonDoesNotExist'>,       'is_relative': <peewee.FieldDescriptor object at 0x000000000470BEF0>, 'name': <peewee.FieldDescriptor object at 0x000000000470BF60>, '_meta': <peewee.ModelOptions object at 0x000000000470BE48>, 'birthday': <peewee.FieldDescriptor object at 0x000000000470BF98>, 'id': <peewee.FieldDescriptor object at 0x000000000470BEB8>, '__module__': 'data', '_data': None, '__doc__': None})

You could see clearly what meta class means in the __dict__,and you can change it in this way:

 setattr(Person._meta, "db_table", "another")

 db.connect()
 db.create_table(Person)

I'm not a native English speaker and a newbie in programming,but I hope the solution is helpful for you.

Jason_n
  • 21
  • 3
0

Using the "exec" function would be easiest way of doing this:

CLASS_TEMPLATE = """\
class %s(peeww.Model):
    pass
"""

classname = "cats"
exec(CLASS_TEMPLATE % classname)

c = cats()   # works !

Explanation:

I've created a string named CLASS_TEMPLATE which contains Python code creating a class. I use a format specifier %s as a class name, so it can be replaced.

Doing this:

CLASS_TEMPLATE % "cats"

replaces the format specifier %s and creates a string that contains the code to create a class named "cats".

If you ask Python to execute this code, your class gets defined:

exec(CLASS_TEMPLATE % "cats")

You can see that it exists in your namespace:

>>> globals()
{..., 'cats': <class __main__.cats at 0x1007b9b48>, ...}

... and that it is a class:

>>> type(cats)
<type 'classobj'>

And you can start using this newly defined class to instantiate objects:

c = cats()
Saish
  • 511
  • 3
  • 11
  • Hi, this looks like it will get me on the right track, however im a newbie and I find it a bit confusing. Do you think you could provide me a clearer example of how to implement this? – Byron Hill Sep 12 '14 at 09:34
  • If you tell me what about this example confuses you I can make it more clear. – Saish Sep 12 '14 at 23:22