web-dev-qa-db-fra.com

Django erreur: doit avoir une valeur pour le champ "..." avant que cette relation plusieurs-à-plusieurs puisse être utilisée

Lors de l'enregistrement d'un formulaire, j'obtiens cette erreur: "" doit avoir une valeur pour le champ "surveythread" avant que cette relation plusieurs-à-plusieurs puisse être utilisée.

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

Message d'erreur:

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

Je suis nouveau sur Django et Python. Je peux publier la trace de débogage ou le fichier de migration si nécessaire, mais j'ai l'impression que c'est une solution simple. Évidemment, le fait est que je veux enregistrer plusieurs sondages fil pour chaque résultat de l'enquête.

Merci!

47
tlovett1

Ok, le code est légèrement désordonné, je suis sûr que vous ferez mieux résoudre votre problème avec ModelForms . Il me semble que le problème est en fait la ligne:

s.survey = self.survey

parce que l'objet s n'a pas encore été écrit dans la base de données, donc l'accès à son champ survey ManyToMany peut générer des problèmes. Si vous voulez copier le même ensemble d'enquêtes de self vers s vous devez le faire en les itérant comme ceci:

Si cela donne la même erreur, essayez de faire d'abord s.save() puis copiez les éléments:

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

Votre code est susceptible de rester comme ceci:

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

Je peux voir que vous avez un if commit: Pour persister l'objet, essayez donc de prendre en compte le code pour l'utiliser. Si la première version de ma réponse a fonctionné, alors vous serez d'accord avec la s.save() à la fin, si la seconde est celle qui a fonctionné, alors vous devrez ajuster un peu le code pour vous y tenir la valeur commit.

J'espère que cela t'aides!

43
Paulo Bu

Dans cette partie du code en forms.py, vous définissez le champ survey de l'objet SurveyThread sur None, mais il n'est pas autorisé d'être None selon votre models.py:

def save(self, commit=True):
    s = SurveyThread()
    s.survey = None     ### This is the problem
    s.email = "[email protected]"
    s.comment = self.cleaned_data['comment']

    if commit:
        s.save()
    return s

Vous devez définir survey sur un objet SurveyResult avant de pouvoir l'enregistrer ou lui permettre d'être None dans le modèle.

Je pense que vous voulez le changer pour dire:

s.survey = self.survey
4
Ben