Sorry for not posting an example, I was in a bit of a rush.  Now that I
am at work I can afford a little longer explanation ;)

I have played with the problem more and have come to a conclusion that
it may be an issue with modifying ManyToMany relationships from the
admin interface through a custom save().

So, here is a simplified example which illustrates the problem.
Consider the following:

        class Genre(models.Model):
                name = models.CharField(maxlength=100)

                class Admin:
                        pass

                def __str__(self):
                        return self.name

        class Movie(models.Model):
                title = models.CharField(maxlength=200, blank=True)
                genres = models.ManyToManyField(Genre, blank=True)

                class Admin:
                        pass

                def __str__(self):
                        return self.title

                def save(self):
                        if not self.title:
                                self.title='you forgot a title'         
#default title

                        super(Movie, self).save()               #call 'real' 
save()

                        if not self.genres.all():
                                try:
                                        genre=Genre.objects.get(name='default') 
        #default genre
                                except:
                                        genre=Genre(name='default')
                                        genre.save()
                                self.genres.add(genre)  #this doesn't appear to 
be called through
the admin interface

when you save a 'Movie' without a 'title' and no 'genres' the save()
method adds a default 'title' and --should-- add a default 'genre'.
When you do this from the web admin, ONLY the 'title' gets modified.

If you change the save() method to this:

        def save(self):
                self.title='you forgot a title'

                super(Movie, self).save()

                self.title='you forgot a title %s' % (self.id) #this is new
                ...

and hit save, the '/admin/movie/movie/' page will show the new 'Movie'
as:

        'you forgot a title'

but the message at the top says:

        'The movie "you forgot a title 9" was added successfully.'

because the 'title' was changed, but not saved - which makes sense.
This means that not everything after the super() method is being
ignored, however, because the the 'title' is updated but the ManyToMany
relationship IS NOT.

When save() is called within the shell, however, this behaves exaclty
as you would expect it - adding both a default 'title' AND a default
'genre'.

Even adding:
        super(Movie, self).save()

to:
        def save(self):

                ...

                try:
                        genre=Genre.objects.get(name='default')
                except:
                        genre=Genre(name='default')
                        genre.save()
                super(Movie, self).save()       #this was added

Doesn't do anything.  As far as I know you shouldn't need it anyway
because it seems that calling add() to a ManyToMany Field automatically
updates the Object for you.

I did a bit more digging into the problem and found that the it really
seems to be isolated to adding ManyToMany relationships, which have to
be called after the object has been created.  I added the following to
see if there was any issue with ForeignKey relationships being added
after the call to super():

        ...

        class Year(models.Model):
                name = models.PositiveIntegerField(unique=True)

                class Admin:
                        pass

                def __str__(self):
                        return '%d' % self.name

        class Movie(models.Model):
                ...
                year = models.ForeignKey(Year, blank=True, null=True)   #null is
required
                ..

and then I changed the save() as so:

        def save(self):
                ...             #stuff before save

                super(Movie, self).save()       #this is the first save

                if not self.year:
                        try:
                                year=Year.objects.get(name='2000')      #if 
default year doesn't exist,
make it
                        except:
                                year=Year(name='2000')  #if it does, select it
                                year.save()
                        self.year=year  #set default year

                        super(Movie, self).save() #have to call save again!

                ...             #ManyToMany stuff after save

This works and the 'year' is added as '2000' by default, but the
ManyToMany relationship still isn't affected.

ALSO, the admin interface will CREATE the default 'genre' if it doesn't
exist, but it simply WILL NOT add it.

One final note, trying to update the relationship the 'reverse' way
does not work either:
        genre.movie_set.add(self) #does not work in the admin

To reiterate, this is only a problem when using the admin interface and
it seems that it is only a problem when you try to add ManyToMany
relationships; all works as expected from the shell.

I should probably be using a custom AddManipulator anyway, but this way
is simpler and --should-- work.

-Weston


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers
-~----------~----~----~----~------~----~------~--~---

Reply via email to