akumoth/peewee-issues huggingface dataset:
Issue: Cannot have an object initialization on __init__()
Author: GabrielSalla
State: closed
Created: 2018-09-14 20:06:41

I want to criate a logger object to each one of my objects. In the 2.X versions overriding the `_prepare_instance()` to create the logger would work as in the `__init__()` method the object would not have the information yet.

Here's an example:

```python
class Alert(BaseModel):
    id = peewee.PrimaryKeyField()
    module = peewee.ForeignKeyField(BaseModule)
    status = peewee.CharField(index=True)
    level = peewee.IntegerField()
    acknowledged = peewee.BooleanField(default=False)
    created_at = DateTimeTZField(default=time_utils.now)
    solved_at = DateTimeTZField(null=True)

    class Meta:
        database = database

    def _prepare_instance(self, *args, **kwargs):
        super(Alert, self)._prepare_instance(*args, **kwargs)
        self._logger = logging.getLogger(f"({self.module.id}) Alert {self.id}")
```

If, instead of the `_prepare_instance()` method I used the `__init__()` method, the values of `self.module.id` and `self.id` would be None.

In the 3.X the `_prepare_instance()` doesn't exists anymore and looking at the source code, there's no replacement for it, these calls were just removed.

Now, if I want to create the logger object, I need to call a "setup" method manually for each object every time I create a new one or load one from the database.

Is there any plan to make it possible to "prepare the instance" automatically after it's loaded?

No, I have no plans to add such login in 3.x. You could always make the logger a lazy-loaded property...hell that's probably a lot better anyways, right?

```
@property
def _logger(self):
    if not hasattr(self, '_logger_obj'):
        self._logger_obj = logging.getLogger(...)
    return self._logger_obj
```

It's Python, so you can be creative.

Well, never thought about solving it this way. Smart sollution!

Maybe there're more people with a similar problem, would be interesting if this solution of lazy loading an instance object was in the documentation.
Issue: Please support python 3 abstract methods
Author: fluffy-critter
State: closed
Created: 2018-09-12 08:02:24

Since Python 3.4, there has been a mechanism for declaring abstract base classes and methods thereof, from the [`abc` module](https://docs.python.org/3/library/abc.html). As of Python 3.7, pylint pretty much requires its use; for example, the line:

    self._query = model.Entry.select().where(self._where)

results in the pylint error:

    publ/view.py:89:8: E1111: Assigning to function call which doesn't return (assignment-from-no-return)

As a temporary measure I can simply disable that warning from pylint, but going forward it would be great if peewee were to use `abc.abstractmethod` and `abc.ABC` to suppress these errors and provide abstract base classes in a more declarative, linter-friendly way.


bro-bro...Python is a dynamic language. Peewee uses this dynamism to provide such nice (if I do say so myself) APIs. There will be no ABCs.

Hi, I'm rather disappointed in this response for a number of reasons.

At the very least I would like to be able to run pylint against peewee without getting a bunch of spurious E1111 notifications, and there are many mechanisms that peewee could use to provide that ability. ABCs were the most readily-obvious ones but there are other approaches as well.

I also don't really care for the condescending tone of your response. I realize that peewee is a volunteer effort that you do for your own needs but it's also part of a greater ecosystem.

Also, I'm not a bro.
Issue: Connect to DB only if not connected already
Author: mekanix
State: closed
Created: 2018-09-11 01:14:15

When testing Flask apps, failure is "peewee.OperationalError: Connection already opened." I used the same logic inside connect_db as the one used in close_db.

I'll pass, because in my opinion an unclosed connection is a bug and this could lead to sloppy programming. You are welcome to subclass this in your own app and override the method as you like, however.

Maybe I wasn't clear enough, so I apologize. If you use FlaskDB with `sqlite:///:memory:`, there is no test you can write that won't break with mentioned error, so if there is a bug, it's on PeeWee side. Other DBs are fine and don't throw an error. Subclassing is OK, but I think it would be better if it would work without the subclass. I can write the simplest showcase, if needed. Also, if you think finding why multiple connections are opened, that's fine too, but I wonder why the same check is OK in `close_db` but isn't in `connect_db`?

> If you use FlaskDB with sqlite:///:memory:

Well, yes -- of course this will not work because every time you connect or close the connection, the data goes away. If you want to use an in-memory sqlite database, then obviously FlaskDB won't work for you.

The check is not present in connect_db() because an already-opened connection at that point indicates a dangling / unclosed connection from somewhere in the app.

OK, I didn't know one should not use FlaskDB with :memory: for tests. What would be the appropriate way to have sqlite in dev, sqlite:///:memory: in test and postgresql in production? As I already have different config class for each of them, should I use `SqliteDatabase` and `PostgresqlDatabase` classes in config? I did try closing DB in tearDown, but I still get this error. So, to put it short, how should I use sqlite:///:memory: for tests with pytest or nose?
Issue: I want to strip string values in my schema, what is the best way to achieve this?
Author: moar55
State: closed
Created: 2018-09-10 13:58:49

I thought of using the `pre_save` but I am not sure if this is the optimal method.

Presumably you would do any data-processing before throwing it into Peewee...Peewee is your layer for talking to the database, in a clean design it should probably not also be your business-logic layer. You're probably best off just overriding the `save()` method rather than messing with the signals API, though of course that's an option.

Thanks!
Issue: Using `in_` with a subquery applies a table alias to the subquery
Author: iksteen
State: closed
Created: 2018-09-09 21:07:40

When using `in_` with a subquery, a table alias is applied to the subquery in the final SQL statement which results in an invalid SQL statement.

F.e. the sample below produces the following SQL statement. Notice the `AS "t3"` part.
```sql
SELECT ("t1"."team_id" IN (SELECT "t2"."id" FROM "team" AS "t2" WHERE ("t2"."id" = 1)) AS "t3") FROM "user" AS "t1" LIMIT 1 OFFSET 0
```

Minimal example:

```python
import logging
logging.basicConfig(level=logging.DEBUG)
from peewee import *

database = PostgresqlDatabase('scoreboard')

class Base(Model):
    class Meta:
        database = database

class Team(Base):
    name = TextField(unique=True)
    
class User(Base):
    username = TextField(unique=True)
    team = ForeignKeyField(Team, null=True, backref='members')

subquery = Team.select().where(Team.id == 1)
User.select(User.team_id.in_(subquery)).get()
```

This yields the following output:
```
DEBUG:peewee:('SELECT ("t1"."team_id" IN (SELECT "t2"."id" FROM "team" AS "t2" WHERE ("t2"."id" = %s)) AS "t3") FROM "user" AS "t1" LIMIT %s OFFSET %s', [1, 1, 0])
Traceback (most recent call last):
  File "/home/ingmar/.virtualenvs/scoreboard-api-a2XBUqg6/lib/python3.7/site-packages/peewee.py", line 2653, in execute_sql
    cursor.execute(sql, params or ())
psycopg2.ProgrammingError: syntax error at or near "AS"
LINE 1: ..."."id" FROM "team" AS "t2" WHERE ("t2"."id" = 1)) AS "t3") F...
```

That is a kind of weird construction...typically wouldn't you write instead:

```python
subquery = Team.select().where(Team.id == 1)
query = User.select().where(User.team.in_(subquery))
```

In this minimal example, perhaps. The actual use of this construction will of course be more complex (both the primary and subquery) and I need the boolean result of the `in` statement alongside other data.

Fixed, thanks for reporting.

Awesome! Thanks for the fast fix.
Issue: Is there tinyint type in models?
Author: moar55
State: closed
Created: 2018-09-09 12:18:16


Refer to [this table](http://docs.peewee-orm.com/en/latest/peewee/models.html#field-types-table) for fields that are currently supported in peewee.

For any other database specific types, you can easily create a [custom field](http://docs.peewee-orm.com/en/latest/peewee/models.html#creating-a-custom-field).

Example:
```
class TinyIntegerField(IntegerField):
    field_type = 'TINYINT'
```

ok thanks!

Btw do you think it really matters perforamnce wise if i switch to tinyint?
This is a field with a value from 1 to 5.

You won't get any performance gain from peewee itself.

But depending on your database implementation/set up in regards to indexing, storage and so forth, you might see some gain.

Thanks!
Issue: How do I make table names plural?
Author: moar55
State: closed
Created: 2018-09-09 08:56:26

I like the default table naming function except that I want table names to be plural. How do I achieve this easily?

You can easily override the default naming.

```
class Project(Model):
    class Meta:
        table_name = 'projects'
```

See [here](http://docs.peewee-orm.com/en/latest/peewee/models.html#model-options-and-table-metadata) for more.

I knew about this I was thinking of making the table name function automatically append the 's' at the end of the table name. But I guess this is good enough too...

You can of course do a custom class that will create the model to be used with a generated table name .

https://github.com/coleifer/peewee/blob/ccf8ac09e6cd571a3becea0b31af9418fcb05a94/playhouse/kv.py#L55

Look at the above class for an example how to accomplish that.

Bit of a tricky case determining plurals, simply adding "s" doesn't make every word automatically plural, but if you use simple words, I guess you'll be fine.

There is an example of a custom table naming function here: http://docs.peewee-orm.com/en/latest/peewee/models.html#table-names

Code from docs:

```python
def make_table_name(model_class):
    model_name = model_class.__name__
    return model_name.lower() + '_tbl'

class BaseModel(Model):
    class Meta:
        table_function = make_table_name

class User(BaseModel):
    # table_name will be "user_tbl".

class UserProfile(BaseModel):
    # table_name will be "userprofile_tbl".
```
Issue: What is the difference between backref and related_name and some other peewee convetions?
Author: rlvillacarlos
State: closed
Created: 2018-09-05 23:50:09

Hi, I am trying out for the first time peewee + flask and python. For starter, I am trying to create a simple Todo app.I have some question regarding how peewee handles foreign key relations. My background is PHP and I have some experience using Eloquent. 

First, I am quite confused as to what to use when setting the attribute of the parent model from the child model when defining `ForeignKeyField`. I have seen examples using `backref `and others using `related_name`, are they the same?

Secondly, I have stored each of my model in a separate python file under the `application.models` package. For example, my `Base` model is stored in `base.py`, the `User` model in `user.py` and so on. Now I have a `ToDo` model with a foreign key from the `User` model. I defined a foreign key called `owner` and a `backref` called `todos`. Now given a `User` object `user`, I want to list all the to do of  `user` so I passed `user.todos` to my view. My Flask app is defined in a separate `app.py` file, so naturally I will import the `User` class. However, as it turns out, calling `user.todos` will result to an exception if the `Todo` model is not imported too. I find this behavior a little unusual. I am thinking maybe this is due to how python handles import. Am I right?

Lastly, I want to know what are the conventions peewee expects from the table structure. All my tables have `id` as the `primary key`, which is something Eloquent expects from a table by default. I found out that this is not the case for peewee so I need to define the field name and its related field name in a `ForeignKeyField`. 

`backref` is the correct way -- `related_name` was used prior to Peewee 3.0 and is deprecated, but they have the same effect.

You are running into a circular import problem. Consider re-architecting your modules or become more familiar with how python imports work.

Peewee follows the convention of using `id = AutoField()` (which is an auto-incrementing integer primary key). If no primary key is specified explicitly by the user, then the model will automatically have this `id` field.

```python
class Todo(Model):
    task_name = TextField()

class TodoItem(Model):
    todo = ForeignKeyField(Todo, backref='items')
    item_name = TextField()
```

You can also explicitly specify the column the foreign-key references by specifying "field=...". The following is equivalent to the above.

```python
class TodoItem(Model):
    todo = ForeignKeyField(Todo, field='id', backref='items')
    ...
```

Thanks @coleifer! I would reread the version of the documentation I am using.  I think I did not see most of what you just have said about ForeignKeyField parameters and column/field name convention in the documentation. Anyways, thanks for the clarification.
Issue: is the connection closed?
Author: bfdcq
State: closed
Created: 2018-09-03 07:00:52

```
[2018-09-03 15:57:10] [pool:152] [DEBUG] Connection 140187317752720 was stale, closing.
[2018-09-03 15:57:10] [peewee:2612] [DEBUG] close <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.2.99', 46786), raddr=('192.168.3.78', 3306)> 
[2018-09-03 15:57:10] [pool:135] [DEBUG] No connection available in pool.
[2018-09-03 15:57:10] [peewee:3391] [DEBUG] open <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.2.99', 46790), raddr=('192.168.3.78', 3306)>
[2018-09-03 15:57:10] [pool:166] [DEBUG] Created new connection 140187317752720.
```
the ids are the same, does that mean that the connection is not closed?
Issue: sql LENGTH function convert to peewee expression
Author: mouday
State: closed
Created: 2018-09-03 03:53:00

sql `select * from table  where  LENGTH(name) < 45`

can I convert to peewee expression? thank you!

```.where(fn.LENGTH(SomeModel.name) < 45)```

http://docs.peewee-orm.com/en/latest/peewee/querying.html#filtering-records

thank you
Issue: model_to_dict don't work with ManyToManyField
Author: Martin25699
State: closed
Created: 2018-08-24 15:40:57

Example code
```
import datetime
from peewee import *
from playhouse.shortcuts import model_to_dict
from playhouse.postgres_ext import PostgresqlExtDatabase

db = PostgresqlExtDatabase('test', user='test', password='tes', host='127.0.0.1', port=5432)


class BaseModel(Model):
    class Meta:
        database = db


class Tweet(BaseModel):
    content = TextField()
    timestamp = DateTimeField(default=datetime.datetime.now)


TweetUserProxy = DeferredThroughModel()


class User(BaseModel):
    username = TextField()
    tweets = ManyToManyField(Tweet, through_model=TweetUserProxy, backref='users')


class TweetUser(BaseModel):
    user = ForeignKeyField(User)
    tweet = ForeignKeyField(Tweet)


TweetUserProxy.set_model(TweetUser)

db.connect()
db.create_tables([User, Tweet, TweetUser])
user = User.create(username='Ivan')
tweet = Tweet.create(content='Hello World!')
TweetUser.create(user=user, tweet=tweet)
tweet2 = Tweet.create(content='Hello Not World!')
TweetUser.create(user=user, tweet=tweet2)

users = User.select()
for u in users:
    user_dict = model_to_dict(u, manytomany=True)
    print(user_dict)
```
Text error
```
Traceback (most recent call last):
  File "/Users/martin/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/182.4129.34/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1664, in <module>
    main()
  File "/Users/martin/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/182.4129.34/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1658, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "/Users/martin/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/182.4129.34/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1068, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/Users/###/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/182.4129.34/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/Users/###/PycharmProjects/###/models/test.py", line 44, in <module>
    user_dict = model_to_dict(u, manytomany=True)
  File "/Users/###/PycharmProjects/###/venv/lib/python3.6/site-packages/playhouse/shortcuts.py", line 63, in model_to_dict
    for rel_obj in getattr(model, name):
TypeError: getattr(): attribute name must be string
```

Thanks for reporting, this is now fixed.

thx! so fast) when next release?

There are quite a few changes, I'll probably tag 3.7.0 here in the next week or so.
Issue: Classic many-to-many relation
Author: inox9
State: closed
Created: 2018-08-24 15:11:50

Hello!
I have a strange problem doing classic many-to-many relation join. I use an intermediate table as suggested in official docs for this. I have enabled query log and noticed that despite join query is correct and actually returns everything that I need there are still additional excess queries done. Here are the models I use:

```python
class Account(IModel):
    balance = MoneyField()
    number = IntegerField(null=False)
    name = CharField(max_length=64, null=False)
    type = SmallIntegerField(null=False)
    updated = DateTimeField(null=True)

class Code(IModel):
    type = SmallIntegerField(null=False)
    code = CharField(max_length=25, null=False)
    description = CharField(max_length=100, null=False)
    parent_code = ForeignKeyField('self', default=0)

class AccountCode(IModel):
    code = ForeignKeyField(Code, null=False)
    account = ForeignKeyField(Account, backref='codes', null=False)
    balance = MoneyField()
```

And this is the query:

```python
acc = (Account
        .select(Account, AccountCode, Code)
        .join(AccountCode)
        .join(Code)
        .where(Account.id == account_id))
for acc_code in acc[0].codes:
        # do something with acc_code and acc_code.code
```

And here is the query log:
```sql
('SELECT `t1`.`id`, `t1`.`balance`, `t1`.`number`, `t1`.`name`, `t1`.`type`, `t1`.`updated`, `t2`.`id`, `t2`.`code_id`, `t2`.`account_id`, `t2`.`balance`, `t3`.`id`, `t3`.`type`, `t3`.`code`, `t3`.`description`, `t3`.`parent_code_id` FROM `account` AS `t1` INNER JOIN `account_code` AS `t2` ON (`t1`.`id` = `t2`.`account_id`) INNER JOIN `code` AS `t3` ON (`t3`.`id` = `t2`.`code_id`) WHERE (`t1`.`id` = %s)', [1])
('SELECT `t1`.`id`, `t1`.`code_id`, `t1`.`account_id`, `t1`.`balance` FROM `account_code` AS `t1` WHERE (`t1`.`account_id` = %s)', [1])
('SELECT `t1`.`id`, `t1`.`type`, `t1`.`code`, `t1`.`description`, `t1`.`parent_code_id` FROM `code` AS `t1` WHERE (`t1`.`id` = %s) LIMIT %s OFFSET %s', [9420, 1, 0])
('SELECT `t1`.`id`, `t1`.`type`, `t1`.`code`, `t1`.`description`, `t1`.`parent_code_id` FROM `code` AS `t1` WHERE (`t1`.`id` = %s) LIMIT %s OFFSET %s', [9423, 1, 0])
```

As you can see there are 3 additional excess queries done which really shouldn't happen in case of join (afaik).

Rather than querying from the perspective of Account (which may have 0..n codes), you should query from the intermediary model and eagerly load the associated account/code:

```python
query = (AccountCode
        .select(AccountCode, Account, Code)
        .join_from(AccountCode, Account)
        .join_from(AccountCode, Code)
        .where(AccountCode.account = account_id))
for acc_code in query:
    # acc_code.account or acc_code.code are already loaded so no more queries
```

For your example to work, peewee would have to de-duplicate data to ensure all the codes were assigned to a single account.
Issue: Add possibility to add constrains in schema migrations
Author: rominf
State: closed
Created: 2018-08-24 04:39:52


This is already possible, if I understand the request correctly.

When adding a new column, you can add arbitrary constraints:

```python
price = FloatField(default=0., constraints=[Check('price >= 0.0')])
migrator = SchemaMigrator.from_database(db)
# Add the "price" column, which includes a CHECK() constraint.
migrate(migrator.add_column('some_table', 'price', price))
```

Perhaps you were referring to table constraints? e.g. `ALTER TABLE ADD CONSTRAINT ...`?

Added support for adding/dropping generic table constraints: https://github.com/coleifer/peewee/commit/128e41ce16473baaeb24cc74864a088884a7e0cb#diff-77fadcec703631c9bc463a8865569f1bR2999
Issue: Clause equivalent in version 3
Author: djsutherland
State: closed
Created: 2018-08-22 23:35:47

I was using [this hack](https://github.com/coleifer/peewee/issues/1181#issuecomment-274626273), which worked in peewee 2, but `peewee.Clause` seems to not be a thing anymore.

How can I pass a `SEPARATOR` argument to `GROUP_CONCAT` in peewee 3?

```python
from peewee import NodeList

fn.GROUP_CONCAT(NodeList((
    MyModel.test_score.distinct(), 
    SQL('ORDER BY'), 
    MyModel.test_score.desc(), 
    SQL('SEPARATOR \' \''))
))
```

INTO:

```sql
GROUP_CONCAT(DISTINCT "t1"."test_score" ORDER BY "t1"."test_score" DESC SEPARATOR ' ')
```

Cool, thanks. :)
Issue: Reflection: Fix broken SQL statement for text-typed default values.
Author: stlehmann
State: closed
Created: 2018-08-21 10:00:26

When using the refection module on text-typed (unicode on py2, str on py3) Columns with default values there were parantheses missing around the generated SQL statement. That leads to errors on model migration.

I fixed this error by checking the data type of the default value and adding parantheses around it if it is a text type.


You mean quotation marks, not parentheses...

I think the better way to fix this would be to introspect the field type rather than the default value.

You are right ... "quotation marks" it is. 

I decided to check the type of the default value because even if you have a certain numeric field type the default value could be any type depending on the users input. E.g. the following is certainly possible:

    import peewee as pw
    class A(pw.Model):
        name = pw.CharField(default=1)
        num = pw.IntegerField(default="foo")

I know it makes no sense but peewee allows to set defaults that don' t match the field type. Maybe that should get checked, too. But to prevent the SQL-statement from breaking it seams better to me to check the type of the default value.
Issue: Missing documentation of a backwards incompatible change from 2.x
Author: CriseX
State: closed
Created: 2018-08-17 22:46:41

The removal of old SelectModel.annotate() method is not listed under the list of backwards incompatible changes. I had to actually dig through the old 2.x documentation to figure out what that method used to do. Perhaps the current documentation could at least link to 2.x documentation on the 3.0 changes page in regards to this method (when noting it has been removed).

Edit: Same is true for "upsert()" on insert by the looks of it (sans the fact that there are obvious alternatives in existence).