Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#17253 closed New feature (wontfix)

Add foreign object in memory without saving to database

Reported by: cyberkoa@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by lukeplant)

Similar to the following post
http://stackoverflow.com/questions/7908349/django-making-relationships-in-memory-without-saving-to-db?answertab=active#tab-top

class Group:
   name = models.Chars()


   def save():
       super(self, Group).save()
       # access foreign objects
       members = self.groupmember_set.all()
       
      

class GroupMember:
   group = models.ForeignKey(Group)
   member = models.ForeignKey(User)

I have a page to allow people to create Group , and invited existing user to become member.

When form is submitted, Group data and GroupMember data is submitted together.

I would like to override the Group's save function() , and in the save function(), I need to access the GroupMember data.

Example code

g = Group(name='abc')
gm1 = GroupMember(member=user1, group=g)
gm2 = GroupMember(member=user2, group=g)

g.groupmember_set.add(gm1)   # Add to memory , I do not want to save to db immediately
g.groupmember_set.add(gm2)   # Add to memory , I do not want to save to db immediately
g.save()
gm1.save()
gm2.save()

Since the .add() function save the related object to db immediately , causing error.

I do not want to save the Group object first , because it will trigger 2 times save()

Change History (3)

comment:1 Changed 4 years ago by lukeplant

  • Description modified (diff)
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

Formatting fixed, please use 'Preview' to check formatting, thanks.

If we don't save M2M objects to the DB immediately when running add(), when do we save them? save() doesn't do that, we would need a 'flush-everything-to-the-database' call, which we don't have. Adding one would require a fundamental change to the way that the ORM works - essentially something like the unit-of-work pattern in SQLAlchemy.

I'm therefore closing WONTFIX.

Note that saving the Group object first doesn't necessarily mean you need to call save() twice - the add() calls do not need to be followed by save(). (I'm guessing you may have reasons why it is this way in your case, but I don't think the situation is forced on you by Django).

comment:2 Changed 4 years ago by cyberkoa@…

Sorry that need to call save() twice. And my case is not as complex as M2M by the way.

Actually my case is as below, we are creating a Sports community website.
When a user create a Sport Group, at the same time , the user can invite other users to join as member .
In this case , each invited users will be created as a record in GroupMember , with status field as "invited"

When this Group is created, we want to notify the users who has set the favourite sport same as the new Group created BUT skip those "invited" members.

If I would like to do it in views.py , it can be done. However , I would like to do it in the models.py because I feel that this code should be in the models.py.

Therefore, I plan to override the save() in Group. In this case , I need to know "invited" users in the save() , so that I can skip them from the notification.

If I save Group before adding the GroupMember , in the save function() , I can't retrieve this information (can I pass parameters ?)

example : I created a football Group

class Group

def save()

super().save() ..


# notify to all users who has 'football' as favourite sport but skip the invited users
notify()


comment:3 Changed 4 years ago by akaariai

Why not add method send_invites to the Group model, and first save the group, then add the members, and then call send_invites. Having a side effect of sending invites to .save() isn't IMHO the way to go. It wouldn't be surprising if you hit a situation where you accidentally send invites because of that side effect.

In short: the use case you have is solvable without altering the behaviour of .add().

Note: See TracTickets for help on using tickets.
Back to Top