【问题标题】:Django ChoiceFieldDjango 选择字段
【发布时间】:2014-08-15 16:28:10
【问题描述】:

我正在尝试解决以下问题:

我有一个只能看到版主的网页。 此页面上显示的字段(用户注册后):
用户名、名字+姓氏、电子邮件、状态、相关性等。

我需要用这个字段显示存储在数据库中的所有用户信息的表格,但是有两个字段有选择,所以我想选择版主可以选择另一个选项,点击“更新”按钮后,这个字段将为选定的用户更新。

我可以显示“状态”和“相关性”字段的所有选项,并且在我从下拉列表中选择新选项后,数据库会更新。
我想显示下拉菜单,并且应该选择存储在 db 中的选项。 我已经尝试了很多选项,我搜索了很多时间,并在 StackOverFlow 中搜索答案或正确的方向,但没有找到任何东西。

对不起,我的英语不好,提前感谢您的帮助!

以下是我的部分代码:

models.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}

模板:

<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>

以下是一个解决方案:

forms.py(正如@Liarez 所写)。

模板:

<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>

【问题讨论】:

    标签: python django choicefield


    【解决方案1】:

    首先我推荐你,因为@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"))
    )
    

    现在你需要在模型上导入它们,这样代码就很容易理解了(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)
    

    您必须在 forms.py 中也导入选项:

    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)
    

    无论如何,您的模板有问题,因为您没有使用任何{{form.field}},您生成了一个表,但没有输入,只有 hidden_​​fields。

    当用户是员工时,您应该生成与您可以管理的用户一样多的输入字段。我认为 django form 不是适合您情况的最佳解决方案。

    我认为使用 html 表单对您来说会更好,因此您可以使用 boucle 生成尽可能多的输入:{% for user in users_list %} 并使用与用户相关的 ID 生成输入,您可以在视图。

    【讨论】:

    • 非常感谢!这对我来说是正确的方向,我按要求做了!
    • 很高兴能提供帮助!
    • 在一个单独但很小的 python 文件中选择并包含它比复制要好。它会在未来的某个时候改变......
    • @ChrisHuang-Leaver 你是对的,我更新了问题
    【解决方案2】:

    如果您的选择不是预先决定的,或者它们来自其他来源,您可以在视图中生成它们并将其传递给表单。

    示例:

    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', )
    

    模板:

    <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>
    

    【讨论】:

      【解决方案3】:

      在 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,
          )
      

      【讨论】:

        【解决方案4】:

        Django 3 中的新方法

        您可以像这样在 django3 中使用 Field.choices 枚举类型新更新:

        from django.db import models
        
        class Status(models.TextChoices):
            UNPUBLISHED = 'UN', 'Unpublished'
            PUBLISHED = 'PB', 'Published'
        
        
        class Book(models.Model):
            status = models.CharField(
                max_length=2,
                choices=Status.choices,
                default=Status.UNPUBLISHED,
            )
        

        django docs

        【讨论】:

          猜你喜欢
          • 2010-11-19
          • 2023-04-08
          • 2018-12-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-02
          • 2013-10-20
          • 2019-05-21
          相关资源
          最近更新 更多