如何使用formset在数据库中以编程方式编辑行?

时间:2016-02-24 10:33:56

标签: python django django-forms formset

我希望我可以在有一个字段时实例化我的字段,而是添加一个直接在数据库中更改值,但是使用我的formset我不能知道如何更改值...

我的models.py:

class Page(models.Model):
    title = models.CharField(max_length=30)


    def __str__(self):
        return self.title

class Question(models.Model):
    label = models.CharField(max_length=30)
    page = models.ManyToManyField(Page)

    def __str__(self):
            return self.label

class Reply(models.Model):
    question = models.ForeignKey(Question)
    user = models.ForeignKey(Personne)
    answer = models.CharField(max_length=30)
    creationDate = models.DateTimeField(default=django.utils.timezone.now)

    def __str__(self):
        return str(self.answer)

和我的views.py:

def access(request, instance):
    questions = Question.objects.filter(page=instance)
    replies = Reply.objects.filter(question=instance)
    pages = Page.objects.all()
    numPages = Page.objects.get(pk=instance)
    length_questions = len(questions)
    logged_user = get_logged_user_from_request(request)
    instance = {'instance':instance}
    ReplyFormSet = modelformset_factory(model=Reply, form=ReplyForm, extra=length_questions)
    ReplyFormSet.form = staticmethod(curry(ReplyForm, instance=numPages))
    if logged_user:
        if request.method == 'POST':  
            formset = ReplyFormSet(request.POST, request.FILES)
            if formset.is_valid():
                new_instances = formset.save(commit=False)
                for new_instance in new_instances:
                    new_instance.user = logged_user
                    new_instance.save()
                return render_to_response('polls/access.html', {
         'formset': formset,
         'questions':questions,
         'logged_user':logged_user,
         'numPages' : numPages
         })
            else:
                messages.add_message(request, messages.INFO, "L'ajout à bien été effectué !")
                return render_to_response('polls/access.html', {
         'formset': formset,
         'questions':questions,
         'logged_user':logged_user,
         'numPages' : numPages
         })
        else:
            formset = ReplyFormSet(queryset = Reply.objects.none())
        return render_to_response('polls/access.html', {
         'formset': formset,
         'questions':questions,
         'logged_user':logged_user,
         'numPages' : numPages
         })
    else:
        return HttpResponseRedirect('/login/')  

和我的模板:

<form method="POST" action="">
    {{ formset.management_form }} {% csrf_token %}
    <table>

      <br>{{ formset.as_table }}<br>

 </table><br>
    <center><input type="submit" value="Submit" class="btn btn-success" />
    <a href="../../baseVisite/" class="btn btn-success">Retour</a></center>
  </form>

我想知道如何实例化我的表单来编辑数据库中的一行。也就是说,如果我已经回答了一个问题,我想改变答案我怎样才能让她成为我的形式?

我无法实例化此行:formset = ReplyFormSet(queryset = Reply.objects.none(), instance=replies)

我收到此错误:__init__() got an unexpected keyword argument 'instance'

Traceback:

File "/home/nicolas/webtrial/dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/home/nicolas/webtrial/dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/nicolas/webtrial/dev/webtrial/polls/views.py" in access
  403.              q_form = QuestionForm(instance=question, prefix='q_'+str(question.id)+'_')

File "/home/nicolas/webtrial/dev/lib/python3.4/site-packages/django/forms/models.py" in __init__
  562.         super(BaseModelFormSet, self).__init__(**defaults)

Exception Type: TypeError at /access/1/
Exception Value: __init__() got an unexpected keyword argument 'instance'

1 个答案:

答案 0 :(得分:1)

您只为所有问题创建了一个ReplyFormset。您需要为每个问题单独form,并在每个问题的回复中单独formset。我还没有测试过,但我认为这对你有用。

forms.py

QuestionForm = modelform_factory(Question)
ReplyInlineFormSet = inlineformset_factory(Question, Reply, extra=1)

views.py

def access(request, page_id):
    page = Page.objects.get(pk=page_id)
    questions = Question.objects.filter(page=page)
    forms = list()
    if request.method == 'POST':
        for question in questions:
            q_form = QuestionForm(request.POST, request.FILES, instance=question, prefix='q_'+str(question.id)+'_')
            r_formset = ReplyInlineFormSet(request.POST, request.FILES, instance=question, prefix=q_form.prefix)
            forms.append((q_form, r_formset))
        if all(q_form.is_valid() and r_formset.is_valid() for q_form, r_formset in forms):
            for q_form, r_formset in forms:
                q_form.save()
                r_formset.save()
    else:
        for question in questions:
            q_form = QuestionForm(instance=question, prefix='q_'+str(question.id)+'_')
            r_formset = ReplyInlineFormSet(instance=question, prefix=q_form.prefix)
            forms.append((q_form, r_formset))
    return render_to_response('polls/access.html', {
        'forms': forms,
    })

template.html

<form method="POST" action="">
{% for form, formset in forms %}
    {{ form }}
    {{ formset }}
{% endfor%}
<input type="submit" value="Submit" class="btn btn-success" />
</form>

这里的主要想法是在创建表单和表单集时使用form参数为每个问题分隔formsetsprefix,以便Django的内部机制可以区分不同的{ {1}}和forms

修改 根据你的追溯,你宣布formsets喜欢

ReplyInlineFormSet

ReplyInlineFormSet = inlineformset_factory(Question, Reply, extra=1, fields=('Question', 'answer')) inlineformset_factory属性中保留模型的字段(此处为fields),并且您将Reply作为'Question'模型没有的字段传递。所以你需要做

Reply