I am trying to add data in a model using django forms but getting
Direct assignment to the forward side of a many-to-many set is prohibited. Use tag.set() instead. Please help me solve this. I am using multiselect field to send data to views.py.
models.py
class Tags(models.Model):
tag = models.CharField(max_length=100)
def __str__(self):
return self.tag
class Meta:
verbose_name_plural = 'Tags'
class Post(models.Model):
...
author = models.ForeignKey(User, verbose_name='Author', on_delete=models.CASCADE)
feature_image = models.ImageField(upload_to='blog/', verbose_name='Add Feature Image')
tag = models.ManyToManyField(Tags, related_name='post_tags', verbose_name='Add Tags')
def __str__(self):
return self.title
forms.py
class PostForm(forms.ModelForm):
...
class Meta:
model = models.Post
fields = [...]
views
def adminNewPostView(request):
form = forms.PostForm()
if request.method == 'POST':
...
tags = request.POST.getlist('tagName')
form = forms.PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.category = cat
if subcat:
post.sub_categories = subcat
if subfil:
post.filter_option = subfil
add_tags = models.Tags.objects.filter(tag__in=tags)
for tl in add_tags:
post.tag = tl # Getting Error here
post.save()
return HttpResponseRedirect(reverse('blog_app:index'))
Error
Direct assignment to the forward side of a many-to-many set is prohibited. Use tag.set() instead.
CodePudding user response:
views.py
def adminNewPostView(request):
form = forms.PostForm()
if request.method == 'POST':
...
tags = request.POST.getlist('tagName')
form = forms.PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.category = cat
if subcat:
post.sub_categories = subcat
if subfil:
post.filter_option = subfil
post.save()
add_tags = models.Tags.objects.filter(tag__in=tags)
for tl in add_tags:
post.tag.add(tl) # new
return HttpResponseRedirect(reverse('blog_app:index'))
to learn more about this please refer to https://docs.djangoproject.com/en/dev/ref/models/relations/
or here https://docs.djangoproject.com/en/2.2/topics/db/examples/many_to_many/#many-to-many-relationships
there is also an other way of doing it.like this
def adminNewPostView(request):
form = forms.PostForm()
if request.method == 'POST':
...
tags = request.POST.getlist('tagName')
form = forms.PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.category = cat
if subcat:
post.sub_categories = subcat
if subfil:
post.filter_option = subfil
post.save()
add_tags = models.Tags.objects.filter(tag__in=tags)
post.tag.add(*add_tags) # new
return HttpResponseRedirect(reverse('blog_app:index'))
CodePudding user response:
A Django form can handle ManyToManyField
s itself, but can only do that with .save_m2m()
or .save()
without using commit=False
: first it needs to save the Post
object since it needs the primary key of that Post
object to link the object to other items.
If your PostForm
uses the tag
field:
class PostForm(forms.ModelForm):
…
class Meta:
model = models.Post
# ↓ tag field
fields = ['tag', 'other', 'fields']
then we can let the form do the work for us:
from django.shortcuts import redirect
def adminNewPostView(request):
form = forms.PostForm()
if request.method == 'POST':
…
tags = request.POST.getlist('tagName')
form = forms.PostForm(request.POST, request.FILES)
if form.is_valid():
if subcat:
form.instance.sub_categories = subcat
if subfil:
form.instance.filter_option = subfil
form.instance.author = request.user
form.instance.category = cat
form.save()
return redirect('blog_app:index')