Issue: Deprecation proposal for Proxy()
Author: foxx
State: closed
Created: 2015-12-28 14:16:09

After reviewing docs and source code, it seems that `Proxy()` is somewhat of an anti-pattern, with most (if not all) edge cases handled by simply moving the database initialization routines before the model definitions. 

Are there any other edge cases that `Proxy()` solves a particular problem for? If not, I'd propose deprecation on the grounds of removing unnecessary complexity, both from the users code and peewee core.

Thoughts @coleifer ?


The only legit use case I can think of is for circular foreign keys. Which are also a code smell...


Ah I hadn't considered this. There are some legit situations where you might need circular foreign keys, for example a self relating [hierarchical table](http://stackoverflow.com/a/3891612/1267398) (with most other situations being an anti pattern). Are there any better ways that circular FK dependancies could be exposed? If not, then `Proxy` deprecation is probably a no-go.


Hierarchical self references are already special cases through the use of
ForeignKeyField('self'). Also many to many junction tables when used with
ManyToManyField.

Honestly, we probably can ditch it and add specific APIs for the valid use
cases.
On Dec 28, 2015 8:32 AM, "Cal Leeming" notifications@github.com wrote:

> Ah I hadn't considered this. There are some legit situations where you
> might need circular foreign keys, for example a self relating hierarchical
> table http://stackoverflow.com/a/3891612/1267398. Are there any better
> ways that circular FK dependancies could be exposed? If not, then Proxy
> deprecation is probably a no-go.
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/coleifer/peewee/issues/799#issuecomment-167581145.


Oh beautiful, I didn't know Peewee had self-referential FKs. In that case, I'm +1 for deprecation.


Alright, so places where `Proxy` is used in the code-base (or tests):
1. To allow circular foreign key dependencies. Example would be `Tweet` has a foreign key to `User` to represent the user who created the tweet, and `User` has a foreign key to `Tweet` to represent the user's favorite tweet.
2. To allow `ManyToManyField()` to reference a custom junction model that, by necessity, has to be defined after both models. This is similar to 1.
3. To allow users to define a database object, reference it in their code, then dynamically assign at run-time. This occurs typically when a user wants to run with one database engine for tests, one for local dev, and one for prod.

To remove `Proxy` I'd like to have suitable replacements for these use-cases. Now, none of these are impossible without Proxy, proxy just makes them convenient and is used in the docs.

Priority-wise, this is very low on my list, since any replacement will necessarily require tests and docs changes, and has potential negative impact on users.

I think I'm going to close this for now and will reopen when I have some time.


Okay sounds good, happy to help if needed. 

For item 3, I've been able to achieve this behaviour easily without `Proxy()`, so I think this can be handled with a good docs example.


Getting a start, added `DeferredRelation` for foreign keys, and `DeferredThroughModel` for many-to-many.


I was thinking about it and while it's a kludge, I think a lot of people have a hard time structuring their code without the Proxy object as a stand-in for their database. I've made some changes, but am going to keep proxy as the recommended way for separating the definition of model classes from a database implementation.


Sounds good, at least we now have `DeferredRelation` and `DeferredThroughModel` for encouraging a better paradigm.