Reputation: 61
I am getting this error while form submission. I know what exactly is causing this error but i seem to be lost here. Actually im trying to use the M2M field as a charfield in my form. According to documentation, the M2M field takes only the list of valid ids and im passing a list of texts. This is the main cause for the error as far as i am informed. Any idea how i can get rid of this error
I have a model structure of:
class Question(models.Model):
topic = models.ForeignKey(Topic, null=True, blank=True)
tag_name = models.ManyToManyField(Tag)
question = models.CharField(max_length = 200)
class Tag(models.Model):
tag_name = models.CharField(max_length = 200)
and in forms.py I have:
class QuestionForm(forms.ModelForm):
tag_name = forms.CharField(widget = forms.TextInput)
class Meta:
model = Question
def clean_tag_name(self):
data = self.cleaned_data
tag_name = data.get('tag_name', None)
if tag_name is not None:
for tags in tag_name.split(','):
try:
tag = Tag.objects.get(tag_name=tags)
except Tag.DoesNotExist:
tag = Tag.objects.create(tag_name = tags)
return tag_name
def save(self, commit=True):
ints = super(QuestionForm, self).save(commit=commit)
tags = self.cleaned_data.get('tag_name', None)
if tags is not None:
for tag in tags.split(","):
tag = QuestionForm.objects.create(name=tag_name)
ints.tag_name.add(tag)
ints.save()
return ints
Upvotes: 2
Views: 1347
Reputation: 1011
Your code snippet has a few flaws:
You can't do QuestionForm.objects.create(name=tag_name)
because QuestionForm
is not a model and has no objects
attribute.
You probably wanted to write Question.objects.create(name=tag_name)
but that wouldn't work as well because Question
has no field name
and you don't have a variable called tag_name
at that point.
Furthermore, in your clean()
method you make sure that the tags the user had entered exist in the database, but in your save()
method you are trying to add the tag names (as in: the strings) and not the tag objects to the M2M field. You can't do that. The .add()
method of the M2M field expects an instance of the Tag
model. This means, in your .save()
method, you have to split your tag strings again, then fetch the Tag
objects from the database and add those instances to the Question
instance you just created.
Try this instead:
First change the class Meta
:
class Meta:
model = Question
fields = ['topic', 'question']
This makes sure that the form doesn't try to save the tag_name
field. This is important, otherwise the super()
call below would try to add something like tag1, tag2, foobar
to the M2M field, which is not possible (remmeber, you can't add strings to an M2M field, you can only add instances).
Then change the save method:
def save(self, *args, **kwargs):
obj = super(QuestionForm, self).save(*args, **kwargs)
tags = self.cleaned_data.get('tag_name', None)
if tags:
for tag in tags.split(","):
tag = Tag.objects.get(tag_name=tag)
obj.tag_name.add(tag)
return obj
Upvotes: 3