问题描述
我有一个表单,当用户试图更新现有的数据库记录时,我希望预先填充模型实例的数据。即使模型实例已被传递给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' )
我的表单
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None None )
class Meta:
model = TestTicket
fields = ['ticket_type']
我的视图
def test_ticket_update(request,ticket_num = None):
#将更新标志初始化为di请求
#添加新的票证或更新到现有票证之间。
update_requested = False
ticket_instance =无
如果ticket_num:
#这是更新特定机票的请求。
#尝试检索机票或显示404错误。
#如果检索到一张票据,则通过使用'select_for_update()'来锁定
#以防止竞争条件。
ticket_instance = get_object_or_404(
TestTicket.objects.select_for_update(),pk = ticket_num)
update_requested = True
如果request.method =='POST':
form = TestTicketForm(request.POST,instance = ticket_instance)
如果form.is_valid():
ticket = form.save(commit = False)
ticket.save()
return HttpResponseRedirect('/ tickets /')
else:
如果update_requested:
#这是一个请求更新现有的票证。
#将票据数据绑定到表单。
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%}
似乎已经。在我的模型中,我在创建ForeignKey字段时使用了 to_field
参数,但是当初始值传递给它时,ModelChoiceField正期待使用该id。在我的示例中有几个选项可以解决这个问题:
- 从模型中的ForeignKey字段中删除to_field参数。
-
在视图中创建表单实例时,使用模型实例中的字段ID为字段设置initial参数,例如
form = TestTicketForm(request.POST,
instance = ticket_instance,
initial = {'ticket_type':instance.ticket_type.id)
-
在窗体
__ init __()
方法中设置表单域的初始值。再次,它使用模型实例的字段ID。例如:
class TestTicketForm(ModelForm):
ticket_type = ModelChoiceField(TicketType.objects.all(),
widget = RadioSelect,
empty_label = None)
def __init __(self,* args,** kwargs):
超级(TestTicketForm,self).__ init __(* args,** kwargs)
如果self.instance不是None:
self.initial ['ticket_type'] = self.instance.ticket_type .id
上面的选项#1将需要在我的数据库中进行模式和数据迁移。选项#2和#3是相似的,但我选择了选项#3,因为它使我的视图代码稍微清洁。
I have a form that I want to be pre-populated with data from a model instance when a user is attempting to update an existing database record. When the form is rendered none of the radio buttons pre-selected even though a model instance has been passed to the ModelForm. In a much larger form than listed below, all of the fields except the radio buttons are pre-populated with the correct data from the model instance. How do I get the correct radio buttons pre-selected?
My Models:
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')
My Form
class TestTicketForm(ModelForm):
ticket_type = ModelChoiceField(TicketType.objects.all(),
widget=RadioSelect,
empty_label=None)
class Meta:
model = TestTicket
fields = ['ticket_type']
My View
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})
My Template
{% 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 %}
It appears this has been answered here before. In my model I used the to_field
argument in the creation of the ForeignKey field, but the ModelChoiceField is expecting to use the id when the 'initial' value is passed to it. There are several options to fix this in my example including:
- Remove the to_field parameter from the ForeignKey field in the model.
When creating the form instance in the view, set the 'initial' parameter for the field using the field's id from the model instance, e.g.,
form = TestTicketForm(request.POST, instance=ticket_instance, initial={'ticket_type': instance.ticket_type.id)
Set the form field's initial value in the forms
__init__()
method. Again this uses the field's id from the model instance. For example: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
Option #1 above would require a schema and data migrations in my database. Options #2 and #3 are similar but I chose option #3 since it makes my view code slightly cleaner.
这篇关于Django - 使用RadioSelect Widget使用ModelChoiceField时无法初始化选定的单选按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!