Hello all,
I'm using `session.merge()` within an HTTP handler, I would like to know
which objects have been newly added and which ones have been modified after
`merge()` completes.
Bare with me please ...
I know there are `before_flush`, etc. events exactly for this scenario but
I **only** need to know within the context of my HTTP request handler. I am
already using whole application-server `before_flush`, `before_commit`,
etc for other purposes.
*Here is my use-case scenario:*
Consider an object graph that represents folder with sub-folders and files
(of any depth). For example:
```
/
# root folder
/folder1/file1
# file1 within folder1; folder1 within root
/folder1/folder2/file2
# file2 within folder2; folder2 within folder1; folder1 within root
```
My sqlalchemy model looks like this:
```
class Folder(Base):
...
id = Column(... primary key)
folder_id = Column(... foreign key to parent folder id)
folder = relationship(...
class File(Base):
...
id = Column(... primary key)
folder_id = Column(... foreign key to parent folder id)
folder = relationship(...
```
The HTTP client would like to do a **single** POST containing the new
directory structure with folders and subfolders rearranged containing any
combination of existing files, existing folders, and to-be created new
folders and subfolders. All in a single HTTP POST.
*My current solution is like this:*
Within my HTTP request handler, the POST payload is validated and newly
detached sqlalchemy instances are created (I'm using pyramid, cornice and
marshmallow).
I use `session.merge()` to automatically "create" and/or "update" my object
graph in one shot. Even if this payload object graph contains any
combination of persisted objects and new objects.
For instance, HTTP client wants the following changes ...
/folder3/folder4/folder1/file1
/folder3/folder4/folder1/folder2/file2
... to be applied over ...
/folder1/file1
/folder1/folder2/file2
IOW: client wants to create a new folder3 (containing a new subfolder
folder4); putting folder3 in root; and moving folder1 into folder4 - all in
one shot:
In code, something like this would be happening within marshmallow:
```
folder3 = Folder()
folder4 = Folder()
folder3.append(folder4)
folder4.folders.append(folder1)
```
In my HTTP handler, I'm doing this:
```
folder3 = request.validated['folder']
session.merge(folder3)
```
All this works just fine :)
New folders are created and existing folders and existing files are
shuffled around correctly.
*However*, after the `merge()`, folder3 and folder4 appear in
`session.dirty` while `session.new` is empty. Also folder1 appears in
`session.dirty`. I.e. `session.dirty` has both newly inserted and modified
instances.
I need to know that folder3 and folder4 were newly added so I can tell the
client "newly added folders: folder3, folder4" - client doesn't care about
"updated" folders and/or files, just cares about new folders.
So, looking at `session.new` and `session.dirty` doesn't help me
identifying which objects were newly inserted and which ones were updated.
*How can I know if folder3 was newly added (or any descendant) without
having to query the DB for every object in the POSTed object graph before
passing all down to `session.merge()`?*
I was considering that I could `@event.listens_for('init'...)` within the
context of the HTTP request (perhaps `before_flush`) but there is a
"dragon warning" (https://docs.sqlalchemy.org/en/latest/core/event.html)
about adding/removing events in "high velocity" which sounds like I would
be doing here?
*Any suggestions?*
Perhaps I'm doing this all wrong to start with ... As my last resort, I
could just simplify my API and incrementally build the directory structure
step by step like a normal "filesystem":
folder1 = mkdir('folder1', root)
put_file(file1, folder1)
folder2 mkdir('folder2', folder1)
put_file(file2, folder1)
The disadvantage would be that client would need to sequentially send each
HTTP request one by one in the correct order. Which is the opposite of the
desired use-case scenario.
--
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.