Displaying data from one model and using a form to update another associated by foreign key

StackOverflow https://stackoverflow.com/questions/23395065

  •  12-07-2023
  •  | 
  •  

سؤال

I think this must be very much an elementary Django question but I can't seem to find any documentation that is getting me any closer to solution after a couple of hours of searching.

I have two models - a Question for which there can be one or many Answers. The Answer model refers to the Question model using a foreign key relationship.

I would like the page to serve up a random Question and then allow the user to enter an Answer for that question. I guess where I'm confused is how exactly to use forms or formsets to do this.

Here's my code, stripped down of extraneous elements:

models.py

class Question(models.Model):
    text = models.TextField(unique=True)

class Answer(models.Model):
    question = models.ForeignKey(Question)
    text = models.CharField(max_length=128)

forms.py

class QuestionForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea(attrs={'class':'form-control', 'rows':2, 'placeholder':'Enter your question here'}))

    class Meta:
        model = Question

AnswerFormset = inlineformset_factory(Question, Answer)

views.py

def index(request):
    context = RequestContext(request)
    error = False
    question = Question.objects.order_by('?')[0]    

    if request.POST:
        form = AnswerFormset(request.POST, instance=question)
        if form.is_valid():
            form.save(commit=True)
            return HttpResponse("Success")
        else:
            error = True
            return HttpResponse("Error")
    else:
        form = AnswerFormset(instance=question)
    return render_to_response('index.html', {"question": question, "form": form}, context)

template (index.html)

<form role="form" id="answer_form" method="post" action="">
<p id="question">{{ question.text }}</p>
    {% csrf_token %}
    {{ form }}
    <button type="submit" class="btn btn-warning btn-lg">Answer</button>
</form>

As it currently stands, the page loads and displays the Question and a bunch of input fields with existing Answers associated to that Question with 3 additional blank input fields. I would like to display only one blank input field in which an Answer can be entered. I'm guessing this means manipulating which widget to use on the formset but I'm not sure how.

The submit action isn't working as it stands and I'm probably way off somewhere. I get a "list index out of range" error and I suspect it has something to do with how I'm trying to save the AnswerFormset POST data.

هل كانت مفيدة؟

المحلول

Inspecting inlineformset_factory indicates that you can pass keyword argument extra=1 to cause it to generate one (rather than 3) inline forms as desired:

def inlineformset_factory(parent_model, model, form=ModelForm,
                      formset=BaseInlineFormSet, fk_name=None,
                      fields=None, exclude=None,
                      extra=3, can_order=False, can_delete=True, max_num=None,
                      formfield_callback=None):

Thus:

AnswerFormset = inlineformset_factory(Question, Answer, extra=1)

EDIT: Indeed, the extra keyword documentation confirms this: https://docs.djangoproject.com/en/dev/topics/forms/formsets/#formsets

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top