Save, Signals and Models

4 views
Skip to first unread message

Victor Loureiro Lima

unread,
Jan 15, 2010, 7:22:33 PM1/15/10
to django...@googlegroups.com
Here is the deal:

class MyModel ( models.Model ):
  title = models.CharField( max_length = 100 )
  only_me = models.BooleanField( default = False )

 Question: Whats the proper way to guarantee that no matter how many MyModel's are available in the database, only one of them
will have the only_me set as True? To further clarify things: In the admin, whenever I check the only_me checkbox, and save my model, all other models of this class will have to have its own only_me field set to false.

 As far as I know, there is no other way of doing this unless I iterate over all MyModel' s objects and uncheck them if they are checked, save them, then afterwards check the model that I am actually saving setting the only_me field to True.

 I tried doing this on the actual save() of the model, no success. Everytime I called save on iterated objects, I, of course, got the maximum recursive depth error thrown at me. 
 Fair enough, I quickly thought about signals, hooking my function to post_save(), however I inevitabilly stumbled upon the same
problem: When I called save() on the iterated objects the post_save signal got sent, I would step again in the same function, thus
no cookie for me.
 I jumped over to overriding AdminForm' s save() method, so that I would iterate there on the models unchecking them if necessary, and them returning the proper object, but I stopped that and I said to myself that I must be doing something really stupid, so Im coming to you guys: What would the propper way of doing this?

Thanks in Advance,
Victor Lima

Gabriel Reis

unread,
Jan 15, 2010, 7:54:53 PM1/15/10
to django...@googlegroups.com
Hey Victor,

I can think that a trivial way (I am not sure if it is the best) to do that is to overwrite the save() method of your model:

class MyModel(models.Model):
    title = models.CharField(max_length=100)
    only_me = models.Boolean(default=False)

    def save(self):
        if self.only_me:
            only_me_true = MyModel.objects.filter(only_me=True)
            for obj in only_me_true:
                obj.only_me = False
                obj.save()
        MyModel.save(self)


I would go for that solution. It is easy to implement, it seems clean and it is easy to test as well.

Cheers dude!

Gabriel de Carvalho Nogueira Reis
Software Developer
+44 7907 823942


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.


Victor Loureiro Lima

unread,
Jan 15, 2010, 8:01:42 PM1/15/10
to django...@googlegroups.com
 I think that will not work,when I call the obj.save() I will inevitably step again into my own save() method and the only_me wont be set as False yet, thus the same problem would occur again and again until I get the maximum depth error. I dont think thats an option, ahev you tested this solution? I am far from my box right now, so I cant test it.

Victor Lima

2010/1/15 Gabriel Reis <gabri...@gmail.com>

Mike Ramirez

unread,
Jan 15, 2010, 8:08:06 PM1/15/10
to django...@googlegroups.com
Add in an if statement, one that while cycling through the only_me=True list,
ignores the current model you're saving.

def save(self):
if self.only_me:
only_me_true = MyModel.objects.filter(only_me=True)
for obj in only_me_true:

if obj.id != self.id:


obj.only_me = False
obj.save()
MyModel.save(self)

> >> django-users...@googlegroups.com<django-users%2Bunsubscribe@goo
> >>glegroups.com> .


> >> For more options, visit this group at
> >> http://groups.google.com/group/django-users?hl=en.
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Django users" group.
> > To post to this group, send email to django...@googlegroups.com.
> > To unsubscribe from this group, send email to

> > django-users...@googlegroups.com<django-users%2Bunsubscribe@goog
> >legroups.com> .


> > For more options, visit this group at
> > http://groups.google.com/group/django-users?hl=en.
>

--
What Did Santa Claus Bring You In 1999? (#2)

WEBMASTER OF LINUXSUPERMEGAPORTAL.COM: One of my in-laws gifted me a
CD-ROM containing the text of every "...For Dummies" book ever published.
It's a shame IDG never published "Hiring A Hitman To Knock Off Your
Inlaws... For Dummies", because that's something I'm itching to do. At any
rate, I'm using the CD as a beer coaster.

JESSE BERST: I got a coupon redeemable for the full copy of Windows 2000
when it comes out in February. Win2K is the most innovative,
enterprise-ready, stable, feature-enriched, easy-to-use operating system
on the market. I don't see how Linux can survive against Microsoft's far
superior offering. I ask you: could you get fired for NOT choosing Windows
2000? You bet.

LINUX CONVERT: I kept hinting for a SGI box, but instead my wife got me an
old Packard Bell. Unfortunately, she bought it at CompUSSR, which doesn't
take returns, so I'm stuck with it. I haven't been able to get Linux to
boot on it, so this machine will probably become a $750 paperweight.

signature.asc

Victor Loureiro Lima

unread,
Jan 15, 2010, 8:11:23 PM1/15/10
to django...@googlegroups.com
I did exactelly that, instead of using id I used the slug, which is also unique, so I skipped it,
but the problem still occurs. Either my logic is wrong, or some dumb mistake, but I think that wouldnt work either.

Victor Lima

2010/1/15 Mike Ramirez <gufy...@gmail.com>

Mike Ramirez

unread,
Jan 15, 2010, 8:12:02 PM1/15/10
to django...@googlegroups.com
On Friday 15 January 2010 17:08:06 Mike Ramirez wrote:
> Add in an if statement, one that while cycling through the only_me=True
> list, ignores the current model you're saving.
>
> def save(self):
> if self.only_me:
> only_me_true = MyModel.objects.filter(only_me=True)
> for obj in only_me_true:
> if obj.id != self.id:
> obj.only_me = False
> obj.save()
> MyModel.save(self)
>

Sorry for the bad formatting -- hope this helps.

def save(self, *args, **kwargs):


if self.only_me:
only_me_true = MyModel.objects.filter(only_me=True)
for obj in only_me_true:
if obj.id != self.id:
obj.only_me = False
obj.save()

super(MyModel, self).save(*args, **kwargs)


Mike
--
What upsets me is not that you lied to me, but that from now on I can no
longer believe you.
-- Nietzsche

signature.asc

Mike Ramirez

unread,
Jan 15, 2010, 8:23:39 PM1/15/10
to django...@googlegroups.com
On Friday 15 January 2010 17:11:23 Victor Loureiro Lima wrote:
> I did exactelly that, instead of using id I used the slug, which is also
> unique, so I skipped it,
> but the problem still occurs. Either my logic is wrong, or some dumb
> mistake, but I think that wouldnt work either.
>
> Victor Lima
>

I just rechecked the django docs, the reason post_save() doesn't work is cause
post save is at the _end_ of the save method, end isn't after the save is
executed, but after all the instructions are executed in the save method. Yes
everytime you call save(), even in the loop that bit of code is getting called
all the time.

You should update this in the model admin after the save is complete, send a
custom single or call a manager method (mangers are meant ot work at the table
level, as opposed to models working on the row level) or put this code bit in
a function you call in the model admin after saving. Ideally I would put it
in a custom singal and send that after the save, where ever I needed it.


Mike
--
Do people know you have freckles everywhere?

signature.asc

Eric Chamberlain

unread,
Jan 16, 2010, 1:51:53 PM1/16/10
to django...@googlegroups.com

def save(self, force_insert=False, force_update=False):
if self.only_me is True:
# if this is the new default, set others to False
MyModel.objects.exclude(pk=self.pk).update(only_me=False)

super(MyModel, self).save(force_insert, force_update) # Call the "real" save() method.


--
Eric Chamberlain, Founder
RF.com - http://RF.com/

Victor Loureiro Lima

unread,
Jan 18, 2010, 9:35:34 AM1/18/10
to django...@googlegroups.com
Thanks Eric, that worked like a charm. I've never got to use the update, thus I had no idea of its existence, fair enough that is exactelly what I needed.

Thank you very much, and other who have answered this thread.
Victor Lima

2010/1/16 Eric Chamberlain <er...@rf.com>
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages