Django - 使用带有RadioSelect Widget的ModelChoiceField时无法初始化选定的单选按钮

时间:2013-11-23 23:47:02

标签: django django-forms

我有一个表单,我希望在用户尝试更新现有数据库记录时预先填充模型实例中的数据。当表单被渲染时,即使已将模型实例传递给ModelForm,也没有预先选择单选按钮。在比下面列出的更大的形式中,除了单选按钮之外的所有字段都预先填充了来自模型实例的正确数据。如何预先选择正确的单选按钮?

我的模特:

class TicketType(models.Model):
    type = models.CharField(max_length=15, unique=True)

    def __unicode__(self):
        return self.type.title()


class TestTicket(models.Model):
    ticket_type = models.ForeignKey(TicketType, to_field='type')

我的表格

class TestTicketForm(ModelForm):
    ticket_type = ModelChoiceField(TicketType.objects.all(),
                                   widget=RadioSelect,
                                   empty_label=None)
    class Meta:
        model = TestTicket
        fields = ['ticket_type']

我的观点

def test_ticket_update(request, ticket_num=None):

    # initialize an update flag to distinguish between a request 
    # to add a new ticket or an update to an existing ticket.
    update_requested = False
    ticket_instance = None

    if ticket_num:
        # This is a request to update a specific ticket. 
        # Attempt to retrieve the ticket or show a 404 error.
        # If a ticket is retrieved, it is locked for editing 
        # by using 'select_for_update()' to prevent a race condition.
        ticket_instance = get_object_or_404(
              TestTicket.objects.select_for_update(),pk=ticket_num)
        update_requested = True

    if request.method == 'POST':
        form = TestTicketForm(request.POST, instance=ticket_instance)
        if form.is_valid():
            ticket = form.save(commit=False)
            ticket.save()
            return HttpResponseRedirect('/tickets/')
    else:

        if update_requested:
            # This is a requested to update an existing ticket. 
            # Bind the ticket data to a form.
            form = TestTicketForm(instance=ticket_instance)
        else:
            form = TestTicketForm()

    return render(request, 'ticket_tracker/ticket_update.html', 
                  { 'form': form, 'ticket': ticket_instance})

我的模板

{% block content %}
<div class="container">
        <form action="/tickets/test-ticket/{{ ticket.id }}/" method="post">
            {% csrf_token %}
            {{ form.as_p }}

            <div class="form-group">
                <button type="submit">Save</button>
            </div>

        </form>
</div>
{% endblock content %}

1 个答案:

答案 0 :(得分:1)

看来这是answered here before。在我的模型中,我在创建ForeignKey字段时使用了to_field参数,但是当将“initial”值传递给它时,ModelChoiceField期望使用id。在我的示例中有几个选项可以解决这个问题,包括:

  1. 从模型中的ForeignKey字段中删除to_field参数。
  2. 在视图中创建表单实例时,使用模型实例中字段的id设置字段的“initial”参数,例如,

    form = TestTicketForm(request.POST,
                          instance=ticket_instance,
                          initial={'ticket_type': instance.ticket_type.id)
    
  3. 在表单__init__()方法中设置表单字段的初始值。同样,它使用模型实例中的字段id。例如:

    class TestTicketForm(ModelForm):
         ticket_type = ModelChoiceField(TicketType.objects.all(), 
                                        widget=RadioSelect, 
                                        empty_label=None)
    
    
    def __init__(self, *args, **kwargs):
        super(TestTicketForm, self).__init__(*args, **kwargs)
    
        if self.instance is not None:
            self.initial['ticket_type'] = self.instance.ticket_type.id
    
  4. 上面的选项#1需要在我的数据库中进行架构和数据迁移。选项#2和#3类似,但我选择了选项#3,因为它使我的视图代码稍微清晰。