Python Django ChoiceField
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24403075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django ChoiceField
提问by Denis
I'm trying to solve following issue:
我正在尝试解决以下问题:
I have a web page that can see only moderators.
Fields displayed on this page (after user have registered):
Username, First name+Last name, Email, Status, Relevance, etc.
我有一个只能看到版主的网页。此页面上显示的字段(用户注册后):
用户名、名字+姓氏、电子邮件、状态、相关性等。
I need to display table with information of all users stored in db with this fields, but two of fields have choices, so I want to make option that moderators can choose another option and after clicking on "Update" button this fields will be updated for selected user.
我需要使用此字段显示包含存储在数据库中的所有用户信息的表,但其中两个字段有选择,所以我想设置一个选项,让版主可以选择另一个选项,点击“更新”按钮后,这些字段将被更新选定的用户。
I can to display all choices of "status" and "relevance" fields, and after I choose new options from dropdown db is updated.
I want to display dropdowns and option stored in db should be selected.
I've tried a lot of options, I googled a lot of my time, and searched for answer or for right direction in StackOverFlow too, but didn't find anything.
我可以显示“状态”和“相关性”字段的所有选择,在我从下拉菜单中选择新选项后,数据库会更新。
我想显示下拉列表,并且应该选择存储在 db 中的选项。我尝试了很多选择,我搜索了很多时间,也在 StackOverFlow 中搜索了答案或正确的方向,但没有找到任何东西。
Sorry for my bad english and thank you in advance for help!
抱歉我的英语不好,并提前感谢您的帮助!
Below is part of my code:
以下是我的代码的一部分:
models.py:
模型.py:
class Profile(models.Model):
user = models.OneToOneField(User)
status = models.IntegerField(choices=((1, _("Not relevant")),
(2, _("Review")),
(3, _("Maybe relevant")),
(4, _("Relevant")),
(5, _("Leading candidate"))),
default=1)
relevance = models.IntegerField(choices=((1, _("Unread")),
(2, _("Read"))),
default=1)
forms.py:
形式.py:
class CViewerForm(forms.Form):
status = forms.ChoiceField(label="",
initial='',
widget=forms.Select(),
required=True)
relevance = forms.ChoiceField(widget=forms.Select(),
required=True)
views.py:
视图.py:
@group_required('Managers')
@render_to('reader/view.html')
def admins_view(request):
users_list = Profile.objects.select_related('user').all()
users_dict = dict()
if request.method and request.method == 'POST':
form = CViewerForm(request.POST)
if form.is_valid():
d = form.cleaned_data
# get all selected choices
status_list = request.POST.getlist('status')
relevance_list = request.POST.getlist('relevance')
# get all usernames viewed on page
users_list = request.POST.getlist('username')
# create dict from all those lists
users_dict = zip([user for user in users_list], [status for status in status_list], [rel for rel in relevance_list])
# run through dict and do bulk update
for user_dict in users_dict:
Profile.objects.filter(user__username=user_dict[0]).update(status=user_dict[1], relevance=user_dict[2])
return HttpResponseRedirect(reverse('reader:admins_view'))
else:
form = CViewerForm()
return {'users_list': users_list,
'user': request.user,
'form': form}
template:
模板:
<form class="form-horizontal" action="" method="post" name="update-form" class="well form-inline" id="view_form">
{% csrf_token %}
{{ form.non_field_errors }}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% if user.is_staff %}
<div>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>{% trans 'Username' %} </th>
<th>{% trans 'E-mail' %} </th>
<th>{% trans 'Status' %} </th>
<th>{% trans 'Relevance' %} </th>
</tr>
</thead>
<tbody>
{% for user in users_list %}
<tr>
<td><input type="text" READONLY name="username" value="{{ user.user.username }}"></td>
<td>{{ user.user.first_name }}</td>
<td>{{ user.user.last_name }}</td>
<td>{{ user.user.email }}</td>
<td>{{ user.get_status_display }}</td>
<td>{{ user.get_relevance_display }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<br>
{% endif %}
<div class="form-actions">
<input type="hidden" name="_cmd_personal">
<input type="submit" class="btn btn-info" value="{% trans 'Update' %}" name="update" class="default">
</div>
</form>
Below is a solution:
下面是一个解决方案:
forms.py (as @Liarez wrote).
forms.py(如@Liarez 所写)。
template:
模板:
<form class="form-horizontal" action="" method="post" name="update-form" class="well form-inline" id="view_form">
{% csrf_token %}
{% if user.is_staff %}
{% if users_list %}
<div>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>{% trans 'Username' %} </th>
<th>{% trans 'First name' %} </th>
<th>{% trans 'Last name' %} </th>
<th>{% trans 'E-mail' %} </th>
<th>{% trans 'CV Status' %} </th>
<th>{% trans 'CV Relevance' %} </th>
</tr>
</thead>
<tbody>
{% for user in users_list %}
<tr>
<td><input type="text" READONLY name="username" value="{{ user.user.username }}"></td>
<td>{{ user.user.first_name }}</td>
<td>{{ user.user.last_name }}</td>
<td>{{ user.user.email }}</td>
<td>
<select name="cv_status">
{% for key, status in status_choices %}
{% ifequal user.get_cv_status_display status %}
<option value="{{ user.cv_status }}" selected>{{ user.get_cv_status_display }}</option>
{% else %}
<option value="{{ key }}">{{ status }}</option>
{% endifequal %}
{% endfor %}
</select>
</td>
<td>
<select name="cv_signal">
{% for key, signal in signal_choices %}
{% ifequal user.get_cv_signal_display signal %}
<option value="{{ user.cv_signal }}" selected>{{ user.get_cv_signal_display }}</option>
{% else %}
<option value="{{ key }}">{{ signal }}</option>
{% endifequal %}
{% endfor %}
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<br>
{% endif %}
<div class="form-actions">
<input type="submit" class="btn btn-info" value="{% trans 'Update' %}" name="update" class="default">
</div>
采纳答案by AlvaroAV
First I recommend you as @ChrisHuang-Leaver suggested to define a new file with all the choices you need it there, like choices.py
:
首先,我建议您按照@ChrisHuang-Leaver 的建议定义一个新文件,其中包含您需要的所有选项,例如choices.py
:
STATUS_CHOICES = (
(1, _("Not relevant")),
(2, _("Review")),
(3, _("Maybe relevant")),
(4, _("Relevant")),
(5, _("Leading candidate"))
)
RELEVANCE_CHOICES = (
(1, _("Unread")),
(2, _("Read"))
)
Now you need to import them on the models, so the code is easy to understand like this(models.py):
现在你需要在模型上导入它们,这样代码就很容易理解了(models.py):
from myApp.choices import *
class Profile(models.Model):
user = models.OneToOneField(User)
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
relevance = models.IntegerField(choices=RELEVANCE_CHOICES, default=1)
And you have to import the choicesin the forms.py too:
你也必须在forms.py 中导入选项:
forms.py:
表格.py:
from myApp.choices import *
class CViewerForm(forms.Form):
status = forms.ChoiceField(choices = STATUS_CHOICES, label="", initial='', widget=forms.Select(), required=True)
relevance = forms.ChoiceField(choices = RELEVANCE_CHOICES, required=True)
Anyway you have an issue with your template, because you're not using any {{form.field}}
, you generate a table but there is no inputs only hidden_fields.
无论如何,您的模板有问题,因为您没有使用 any {{form.field}}
,您生成了一个表,但只有 hidden_fields 没有输入。
When the user is staff you should generate as many input fields as users you can manage. I think django form is not the best solution for your situation.
当用户是员工时,您应该生成与您可以管理的用户一样多的输入字段。我认为 django form 不是适合您情况的最佳解决方案。
I think it will be better for you to use html form, so you can generate as many inputs using the boucle: {% for user in users_list %}
and you generate input with an ID related to the user, and you can manage all of them in the view.
我认为使用 html 表单对您来说会更好,这样您就可以使用 boucle: 生成尽可能多的输入,并使用{% for user in users_list %}
与用户相关的 ID 生成输入,并且您可以在视图中管理所有这些输入。
回答by Arindam Roychowdhury
If your choices are not pre-decided or they are coming from some other source, you can generate them in your view and pass it to the form .
如果您的选择不是预先决定的,或者它们来自其他来源,您可以在您的视图中生成它们并将其传递给表单。
Example:
例子:
views.py:
视图.py:
def my_view(request, interview_pk):
interview = Interview.objects.get(pk=interview_pk)
all_rounds = interview.round_set.order_by('created_at')
all_round_names = [rnd.name for rnd in all_rounds]
form = forms.AddRatingForRound(all_round_names)
return render(request, 'add_rating.html', {'form': form, 'interview': interview, 'rounds': all_rounds})
forms.py
表格.py
class AddRatingForRound(forms.ModelForm):
def __init__(self, round_list, *args, **kwargs):
super(AddRatingForRound, self).__init__(*args, **kwargs)
self.fields['name'] = forms.ChoiceField(choices=tuple([(name, name) for name in round_list]))
class Meta:
model = models.RatingSheet
fields = ('name', )
template:
模板:
<form method="post">
{% csrf_token %}
{% if interview %}
{{ interview }}
{% endif %}
{% if rounds %}
<hr>
{{ form.as_p }}
<input type="submit" value="Submit" />
{% else %}
<h3>No rounds found</h3>
{% endif %}
</form>
回答by santhosh_dj
Better Way to Provide Choice inside a django Model :
在 Django 模型中提供选择的更好方法:
from django.db import models
class Student(models.Model):
FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
GRADUATE = 'GR'
YEAR_IN_SCHOOL_CHOICES = [
(FRESHMAN, 'Freshman'),
(SOPHOMORE, 'Sophomore'),
(JUNIOR, 'Junior'),
(SENIOR, 'Senior'),
(GRADUATE, 'Graduate'),
]
year_in_school = models.CharField(
max_length=2,
choices=YEAR_IN_SCHOOL_CHOICES,
default=FRESHMAN,
)