Reputation: 5228
i am working on saving on the same form two tables - having a m2m relation. I don't succeed, my error persists with something like: Cannot set values on a ManyToManyField which specifies an intermediary model. Use Membership's Manager instead where Membership is my 'through table'.
my code :
def save_classroom(request):
classroom_instance = Classroom()
if request.method == 'POST':
form = ClassroomForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.user = request.user
new_obj.save()
membership = Membership(member = request.user,classroom=new_obj)
membership.save()
form.save_m2m()
return HttpResponseRedirect('.')
else:
form = ClassroomForm(user = request.user)
return render_to_response('classroom/classroom_form.html', {
'form': form,
},
context_instance=RequestContext(request))
my models:
class Classroom(models.Model):
user = models.ForeignKey(User, related_name = 'classroom_creator')
classname = models.CharField(max_length=140, unique = True)
date = models.DateTimeField(auto_now=True)
open_class = models.BooleanField(default=True)
members = models.ManyToManyField(User,related_name="list of invited members", through = 'Membership')
class Membership(models.Model):
accept = models.BooleanField(default=False)
date = models.DateTimeField(auto_now = True)
classroom = models.ForeignKey(Classroom, related_name = 'classroom_membership')
member = models.ForeignKey(User, related_name = 'user_membership')
where am i wrong?
Upvotes: 20
Views: 30971
Reputation: 1
As specified in https://docs.djangoproject.com/en/2.1/topics/db/models/
"Unlike normal many-to-many fields, you can’t use add(), create(), or set() to create relationships"
This means for django version 2.1 ,these methods are impossible. But the same page of django 2.2 documentation https://docs.djangoproject.com/en/2.2/topics/db/models/ tells that:
"You can also use add(), create(), or set() to create relationships, as long as you specify through_defaults for any required fields"
So just update the django to 2.2 or newer versions to use the above methods and while creating objects give the argument 'through_defaults' as a python dictionary with keys as your extra field names and values as their default values.
Upvotes: 0
Reputation: 24270
As of the Django 2.2 release you can also specify a through_defaults
on the field in order to use add, create and assignment:
The
RelatedManager.add()
,create()
,remove()
,set()
,get_or_create()
, andupdate_or_create()
methods are now allowed on many-to-many relationships with intermediate models. The newthrough_defaults
argument is used to specify values for new intermediate model instance(s).
In your case since all the fields already have defaults it might just work in 2.2.
Upvotes: 3
Reputation: 1008
If you are allowed to modify class Membership
, adding auto_created = True
might solve your problem,
class Membership(models.Model):
class Meta:
auto_created = True
In Django 1.7, the error message is changed to "Cannot set values on a ManyToManyField which specifies an intermediary model". The solution is the same.
NOTE: This will remove your intermediate model entirely, and all the additional fields with it.
Upvotes: 37
Reputation: 43116
I had a similar error message on a different problem. I post it here just in case it helps others.
I've added a new ManyToManyField
on an existing model. This model was used in a ModelForm
built with an exclude
field.
I fixed the problem by add the new field in the excluded ones.
Upvotes: 4
Reputation: 2528
As seen on:
http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
Unlike normal many-to-many fields, you can't use add, create, or assignment (i.e., beatles.members = [...]) to create relationships
I guess your code trips up on the line "form.save_m2m()", which is unnecessary since you already manually create a membership.
Upvotes: 20