On Wed, Nov 8, 2017 at 5:05 AM, Sven <[email protected]> wrote:
> Hello,
>
> I am actually working on my previous post about the OrderedDict and the None
> values and I met new problems and new questions. I didn't found answers on
> the Internet, so here I am !
>
> As explained in the official documentation (or in the following topic :
> https://groups.google.com/forum/#!msg/sqlalchemy/2dVQTvzmi84/8J8lGpLfw4EJ),
> using backref or back_populates on relationship "sets up the
> "synchronization" of the two directions, which consists of an event that
> performs the complimentary set/append operation when an append/set occurs on
> the other side".
>
> Here is the example gived by the topic previously mentionned :
>
> p = Parent('parent1')
> c = Child('child1')
> c.parent = p
> p.children.append(c)
>
>
> p's children will contain c twice.
>
> In deed, the "c.parent = p" operation results in the "append" on the other
> side, and vice versa.

so the super-duper best way to fix for the above use case, if
possible, would be to use collection_class=set rather than list.
sets are all around better for relationship() and if I was writing
SQLAlchemy today this would have been the default (back in python 2.3,
sets were kind of an exotic feature .... :)  )



>
> In my case, I'm working on an existing project which contains a lot of
> classes and the methods are already designed in order to add the objects on
> the two sides. It is so because the program is using Pickle to persist
> everything (my objectiv is to replace it by SQLAlchemy).

Are you seeing objects that are being unpickled, and then are firing
off SQLAlchemy events such that collections are being populated twice?
  That's not supposed to happen.   Backrefs don't get in the way of
normal pickling / unpickling of collections and attributes, that's how
major functionality like the whole dogpile.cache example work.

Otherwise, I'm not sure how pickling relates to the above code sample
where ".append()" is being explicitly called.


Of course, I could
> adapt the code but it will be a lot of work and I don't like the idea that
> my structures are automatically synchronized without explicit declarations.

backref/back_populates are explicit declarations :)

> Furthermore, what will happen if I decide, one day, to stop using SQLAlchemy
> ? My code would be too dependent on the fonctionnalities provided by
> SQLAlchemy.

if you are using the ORM, then you're buying into the class-state
management solution provided by the ORM as well.  There are hooks to
entirely replace this state management system with your own system,
but building out on that while trying to make your class models
completely agnostic of the fact that something has given them new
attributes and features would be difficult (see
http://docs.sqlalchemy.org/en/latest/_modules/examples/custom_attributes/custom_management.html
for an illustration of these systems).

The idea that an application model can be developed against an ORM and
then be completely swapped out to not use an ORM without alterations
to the usage of the model has long been a popular ideal but I don't
think it has ever played out in practice.  ORMs in all languages apply
a lot of assumptions to a model, and in Python, this is even more
prevalent since Python allows for all the great metaprogramming
features which mean you aren't having to write getter/setters across
all your models, among other things.

If you truly are trying to build out an easy stepping stone out of
ORMs later on, there are two design patterns that come to mind. One is
that you don't change your model at all, and you instead create an
entirely separate model that represents your database mapping.   A
mediation layer then transfers state between your "default" model and
the ORM-enabled model.    FWIW a large swath of Openstack, which I get
paid to work on, works sort of this way.    it's a common pattern that
there is some kind of public-facing "API" model, e.g. the one that
gets converted into JSON and such for services, and the internal
"business" model that knows how to be persisted and is more
application-specific.

The other pattern is to not use the ORM and just use Core.   This is
also a very popular pattern, and a big reason SQLAlchemy Core exists
is specifically to allow all of SQLAlchemy's great database features
to be available to projects that aren't comfortable wiring the whole
object model to SQLAlchemy, or projects that don't really use an
OO-style object model in the first place.

>
> So, my questions are :
>
> 1) Is it feasible to avoid to use backref or back_populates ? Would it be a
> bad idea to work without these fonctionnalities ? Will I face for example
> inconsistent state of the program ?

You can go this road for one-to-many and many-to-one although this is
not a well-traveled use case.

For a many-to-many with "secondary", there can still be some conflicts
because the unit of work uses "backref" to look at the fact that the
two sides represent the same collection to resolve duplicate events
that occur on both sides.


> 2) Is it possible to use back_populates and allow SQLAlchemy to detect that
> it should not append something which was already inserted ?

using collection_class=set is by far the easiest way to do this.


>
>
> Thank you very much !
>
> Regards,
>
> Sven
>
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to