0

I have overridden my save() method on a model, in order to add some ManyToMany objects to it. If I call the super().save() method after I add the objects, I get the classic error that a model needs a PK before adding ManyToMany objects, which is normal. However If I call it both before and after, the objects simply don't get added.

My code looks like this:

def save(self, force_insert=False, force_update=False):
        super(Teacher, self).save(force_insert, force_update)

        from school.models import Course

        disciplinary = Course.objects.filter(type=Course.TYPE_DISCIPLINARY)

        for disc in disciplinary:
            print disc  # this gets called
            self.subjects.add(disc)

        super(Teacher, self).save(force_insert, force_update)

This produces no errors, but doesn't add the appropriate Courses.

4
  • 1
    There shouldn't be any reason to call save after adding the objects. M2m relationships do not affect the model at all, as they are stored on a separate table. Commented Jul 18, 2014 at 12:02
  • 1
    If you are using the Django admin there is a gotcha... when saving the admin will first call save() on your model, then it will add the m2m objects that were submitted in the admin form... if this field was empty it will replace the objects you add in your overridden save method with an empty set Commented Jul 18, 2014 at 12:25
  • @Anentropic just saw that in the source code, and it makes sense based on my results. Commented Jul 18, 2014 at 12:48
  • posted as an answer :) Commented Jul 18, 2014 at 13:13

3 Answers 3

2

If you are using the Django admin there is a gotcha... when saving your parent object the admin will first call save() on your model instance, then it will add the m2m objects that were submitted in the admin form... whatever was selected in the admin form will then replace the objects you add in your overridden save method.

Sign up to request clarification or add additional context in comments.

Comments

0

Seeing that you add just a static course set, you could use post_save signals Django signals post save signal

If it's not a problem just add a new function and call it after save

Teacher.save()
Teacher.save_courses()

I personally don't know a way to make it in the save function, but i can be wrong.

1 Comment

Tried that aswell, but due to the reason in @Anentropic's comment, it also won't work.
0

What I ended up doing was to delay adding of the courses, by using Celery (which I was using anyway on this project), by 5 seconds, at which point DB should be consistent and everything should be available for me to use.

The more reliable solution was to only delay the Celery task by a small amount (<1 second) and re-schedule it if the entry doesn't exist in the DB yet. (It seems that Django doesn't persist the models in the DB right away, but caches them, so that you can get() them in certain places)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.