Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django error: needs to have a value for field "..." before this many-to-many relationship can be used

Tags:

python

django

When saving a form I am getting this error: "" needs to have a value for field "surveythread" before this many-to-many relationship can be used.

Models.py:

class SurveyResult(models.Model):     stay = models.OneToOneField(Stay, related_name='survey')     created = models.DateTimeField(default=datetime.now)     vote = models.BooleanField(default=False)     vote_service = models.BooleanField(default=False)     comment = models.TextField(blank=True, null=True)      def getThreads(self):         return SurveyThread.objects.filter(parent_survey = self)      threads = property(getThreads)      def __unicode__(self):         return self.vote and 'Good' or 'Bad'      class Meta:         get_latest_by = '-created'  class SurveyThread(models.Model):     survey = models.ManyToManyField(SurveyResult, related_name='parent_survey')     email = models.EmailField(max_length=200)     comment = models.TextField(blank=True, null=True) 

views.py:

survey_list = SurveyResult.objects.filter(stay__guest__user=request.user) \                                       .select_related('stay', 'stay__guest')  forms = {} for survey in survey_list:   forms[survey] = SurveyThreadForm(data=request.POST or None, survey=survey)    if forms[survey].is_valid():     instance = forms[survey].save()     return redirect('.') 

forms.py

class SurveyThreadForm(forms.Form):      comment = forms.CharField(required=False, widget=forms.Textarea)      def __init__(self, *args, **kwargs):         self.survey = kwargs.pop('survey', None)          if not self.survey:             raise NotImplementedError("SurveyResult object is required at this moment")          super(SurveyThreadForm, self).__init__(*args, **kwargs)          self.fields['comment'].label = "Message to send to guest:"      def save(self, commit=True):         s = SurveyThread()         s.survey = self.survey         s.email = "[email protected]"         s.comment = self.cleaned_data['comment']          if commit:             s.save()         return s 

Error Message:

ValueError at / "<SurveyThread: SurveyThread object>" needs to have a value for field "surveythread" before this many-to-many relationship can be used. Request Method: POST Request URL:    http://127.0.0.1:8000/ Django Version: 1.5.1 Exception Type: ValueError Exception Value:     "<SurveyThread: SurveyThread object>" needs to have a value for field "surveythread" before this many-to-many relationship can be used. Exception Location: /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/django/db/models/fields/related.py in __init__, line 586 Python Executable:  /Users/tlovett1/.virtualenvs/guestretain/bin/python Python Version: 2.7.2 Python Path:     ['/Users/tlovett1/guestretain',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/pip-1.3.1-py2.7.egg',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python27.zip',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/plat-darwin',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/plat-mac',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/plat-mac/lib-scriptpackages',  '/Users/tlovett1/.virtualenvs/guestretain/Extras/lib/python',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/lib-tk',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/lib-old',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/lib-dynload',  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages',  '/Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/PIL'] Server time:    Sun, 7 Jul 2013 10:22:55 -0500 

Traceback:

Traceback Switch to copy-and-paste view  /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/django/core/handlers/base.py in get_response                         response = callback(request, *callback_args, **callback_kwargs) ... ▶ Local vars /Users/tlovett1/guestretain/retain/apps/profiles/utils.py in _wrapped_view                     return view_func(request, *args, **kwargs) ... ▶ Local vars /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/endless_pagination/decorators.py in decorated             return view(request, *args, **kwargs) ... ▶ Local vars /Users/tlovett1/guestretain/retain/apps/dashboard/views.py in dashboard             instance = forms[survey].save() ... ▶ Local vars /Users/tlovett1/guestretain/retain/apps/surveys/forms.py in save         s.survey = self.survey ... ▶ Local vars /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/django/db/models/fields/related.py in __set__         manager = self.__get__(instance) ... ▶ Local vars /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/django/db/models/fields/related.py in __get__             through=self.field.rel.through, ... ▶ Local vars /Users/tlovett1/.virtualenvs/guestretain/lib/python2.7/site-packages/django/db/models/fields/related.py in __init__                                  (instance, source_field_name)) ... ▶ Local vars 

I'm new to Django and Python. I can post the debug trace or migration file if needed, but I have a feeling it's a simple fix. Obviously the point is I want to save multiple survey thread for each survey result.

Thanks!

like image 254
tlovett1 Avatar asked Jul 06 '13 18:07

tlovett1


People also ask

How to implement many to many relationship in django?

To define a many-to-many relationship, use ManyToManyField . What follows are examples of operations that can be performed using the Python API facilities. You can't associate it with a Publication until it's been saved: >>> a1.

How to add primary key in django?

If you'd like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you've explicitly set Field.primary_key , it won't add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

What is models in Python?

A model is a Python class that inherits from the Model class. The model class defines a new Kind of datastore entity and the properties the Kind is expected to take. The Kind name is defined by the instantiated class name that inherits from db.


1 Answers

Ok, the code is slightly messy, I'm sure you'll be better off tackling your problem with ModelForms. Seems to me the problem actually is the line:

s.survey = self.survey 

because s object hasn't been written to the database yet, so accessing it's survey ManyToMany field can yield problems. If you want to copy the same set of surveys from self to s you should do it iterating over them like this:

If this yields the same error, then try to do s.save() first and later copy the items:

s.save() for item in self.survey:     s.survey.add(item) 

Your code is likely to remain like this:

def save(self, commit=True):     s = SurveyThread()     # these fields aren't problematic     s.email = "[email protected]"     s.comment = self.cleaned_data['comment']     # you can add s.save() here to remove problems associated with object      # not yet persisted     # s.save()     for item in self.survey:         s.survey.add(item)     if commit:         s.save()     return s 

I can see you have a if commit: to persist the object, so try to accommodate the code to make use of it. If the first version of my answer worked then you'll be fine with the s.save() at the end, if the second is the one who worked, then you'll have to adjust the code a little to stick to the commit value.

Hope this helps!

like image 155
Paulo Bu Avatar answered Sep 28 '22 06:09

Paulo Bu