python - initial - Django ChoiceField
forms.select django (2)
Estoy tratando de resolver el siguiente problema:
Tengo una página web que solo puedo ver moderadores. Campos mostrados en esta página (después de que el usuario se haya registrado):
Nombre de usuario, nombre + apellido, correo electrónico, estado, relevancia, etc.
Necesito mostrar la tabla con la información de todos los usuarios almacenados en db con estos campos, pero dos de los campos tienen opciones, por lo que quiero elegir que los moderadores puedan elegir otra opción y luego de hacer clic en el botón "Actualizar", estos campos se actualizarán para usuario seleccionado
Puedo mostrar todas las opciones de los campos "estado" y "relevancia", y después de elegir nuevas opciones de la lista desplegable db se actualiza.
Quiero mostrar desplegables y la opción almacenada en db debe estar seleccionada. He probado muchas opciones, busqué en Google gran parte de mi tiempo y busqué la respuesta o la dirección correcta en StackOverFlow también, pero no encontré nada.
Lo siento por mi mal inglés y gracias de antemano por la ayuda!
A continuación es parte de mi código:
modelos.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 :
class CViewerForm(forms.Form):
status = forms.ChoiceField(label="",
initial='''',
widget=forms.Select(),
required=True)
relevance = forms.ChoiceField(widget=forms.Select(),
required=True)
views.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}
modelo:
<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>
A continuación se muestra una solución:
forms.py (como escribió @Liarez).
modelo:
<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>
Primero, te recomiendo como @ ChrisHuang-Leaver sugirió para definir un nuevo archivo con todas las opciones que necesitas, como choices.py
:
STATUS_CHOICES = (
(1, _("Not relevant")),
(2, _("Review")),
(3, _("Maybe relevant")),
(4, _("Relevant")),
(5, _("Leading candidate"))
)
RELEVANCE_CHOICES = (
(1, _("Unread")),
(2, _("Read"))
)
Ahora necesita importarlos en los modelos, por lo que el código es fácil de entender, como este ( modelos.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)
Y tienes que importar las opciones en el formulario.py también :
forms.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)
De todos modos, tienes un problema con tu plantilla, ya que no estás usando {{form.field}}
, {{form.field}}
una tabla pero no hay entradas solo hidden_fields.
Cuando el usuario es personal, debe generar tantos campos de entrada como usuarios que pueda administrar. Creo que django form no es la mejor solución para su situación.
Creo que será mejor para usted usar el formulario html, de modo que pueda generar tantas entradas usando el boucle: {% for user in users_list %}
y generará una entrada con una ID relacionada con el usuario, y podrá administrar todo ellos en la vista
Si sus elecciones no están predeterminadas o provienen de alguna otra fuente, puede generarlas en su vista y pasarlas al formulario.
Ejemplo:
views.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
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'', )
modelo:
<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>