Django使表单字段可迭代

时间:2017-06-26 14:52:24

标签: django django-forms django-views

无法获取视图以向用户分配角色。我使用django-roles-permissions,一切都在shell中正常工作,但是当我尝试使用表单和视图时,我会遇到多个错误。我认为大部分时间已经弄明白了,而且我只有一个错误:'CharField' object is not iterable。我尝试使用.split(','),但它说它没有split属性。这是我的代码:

forms.py:

ROLES = [[g.id, g.name] for g in Group.objects.all().order_by('name')]

class UserForm(forms.ModelForm):
    first_name = forms.CharField(widget=forms.TextInput(attrs={
        'class': 'form-control',
        'id': 'first_name',
        'tabindex': '1',
    }))
    last_name = forms.CharField(widget=forms.TextInput(attrs={
        'class': 'form-control',
        'id': 'last_name',
        'tabindex': '2'
    }))
    password = forms.CharField(widget=forms.PasswordInput(attrs={
        'class': 'form-control',
        'tabindex': '4'
    }))
    confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={
        'class': 'form-control',
        'tabindex': '5'
    }))
    username = forms.CharField(widget=forms.TextInput(attrs={
        'class': 'form-control',
        'id': 'username',
        'tabindex': '-1',
        'placeholder': 'Automatically generated suggestion...'
        }))
    email = forms.CharField(widget=forms.EmailInput(attrs={
        'class': 'form-control',
        'tabindex': '3'
    }))
    roles = forms.CharField(widget=forms.SelectMultiple(choices=ROLES, attrs={
        'class': 'form-control select2',
        'style': 'width:100%;',
        'multiple': 'multiple',
        'placeholder': 'Click on me to add a role'
    }))

    class Meta:
        model = User
        fields = ('username', 'email', 'password', 'confirm_password', 'first_name', 'last_name', 'roles')

views.py:

@login_required
def create_employee(request):

    registered = False

    if request.method == 'POST':

        # Get info from "both" forms
        # It appears as one form to the user on the .html page
        user_form = UserForm(data=request.POST)
        profile_form = UserProfileForm(data=request.POST)

        # Check to see both forms are valid
        if user_form.is_valid() and profile_form.is_valid():

            # Save User Form to Database
            user = user_form.save()

            # Hash the password
            user.set_password(user.password)
            # Update with Hashed password
            user.save()

            # Now we deal with the extra info!
            # Update roles membership
            roles = user_form.fields['roles']
            for role in roles:
                assign_role(user, role)
            user.save()

            # Can't commit yet because we still need to manipulate
            profile = profile_form.save(commit=False)

            # Set One to One relationship between
            # UserForm and UserProfileInfoForm
            profile.user = user

            # Now save model
            profile.save()

            # Registration Successful!
            registered = True

        else:
            # One of the forms was invalid if this else gets called.
            print(user_form.errors, profile_form.errors)

    else:
        # Was not an HTTP post so we just render the forms as blank.
        user_form = UserForm()
        profile_form = UserProfileForm()

    # This is the render and context dictionary to feed
    # back to the modal_create_user.html file page.
    return render(request, 'pages/create_employee.html', {
        'user_form': user_form,
        'profile_form': profile_form,
        'registered': registered
    })

使用跟踪进行编辑:

Environment:


Request Method: POST
Request URL: http://localhost:8000/employee/create

Django Version: 1.11.2
Python Version: 3.6.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'imagekit',
 'rolepermissions',
 'django_messages',
 'taggit',
 'dispatch']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'dispatch.activeuser_middleware.ActiveUserMiddleware']



Traceback:

File "/home/jboucher/anaconda3/envs/openroad/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/jboucher/anaconda3/envs/openroad/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/jboucher/anaconda3/envs/openroad/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/jboucher/anaconda3/envs/openroad/lib/python3.6/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  23.                 return view_func(request, *args, **kwargs)

File "/home/jboucher/openroad/openroad/dispatch/views.py" in create_employee
  67.             for role in roles:

Exception Type: TypeError at /employee/create
Exception Value: 'CharField' object is not iterable

最新编辑: 现在,无论选择什么,它都会分配每个角色。

# Now we deal with the extra info!
            # Update roles membership
            roles = user_form.fields['roles'].choices
            for role in roles:
                print('%s assigned to %s', role, user)
                assign_role(user, role[1])
            user.save()

2 个答案:

答案 0 :(得分:1)

您可以在此处定义角色:

roles = user_form.fields['roles']

归结为:

  

给我一​​个名为'roles'的字段实例

您可能正在寻找:

roles = user_form.cleaned_data['roles']

但是您已将角色定义为CharField,并使用返回多个值的窗口小部件。因此,您还需要使用MultipleChoiceField修复表单定义。

最后,我想知道你是否真的需要定义所有这些字段。 ModelForm可以从模型定义生成表单字段,并且可以很好地完成它。因此,您应该只关注正确执行的字段。

答案 1 :(得分:1)

这里有几个问题。

首先,表单fields dict包含字段对象本身。它不包含输入这些字段的数据;它以cleaned_data dict。

的形式出现

其次,您使用了错误的字段类型。顾名思义,CharField用于字符串。但是您需要一个选项列表,用户可以从中选择多个选项 - 因此您应该使用MultipleChoiceField