Django 表单 'int' 对象没有 'required' 属性,字段是在函数中添加的

0 投票
1 回答
2167 浏览
提问于 2025-04-18 00:04

在Django 1.6和crispy forms中,我想在用户提交表单后添加一个叫做 forum_id_number 的字段,这个字段的值是从API调用中返回的。不过,我在提交表单后遇到了一个

Exception Value:    
'int' object has no attribute 'required'

的错误。我确认是 self.fields['forum_id_number'] = response["User"]["Id"] 这行代码导致了这个问题。


class AccountForm(forms.ModelForm):
    class Meta:
        model = Employee

    def __init__(self, *args, **kwargs):
        super(AccountForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-lg-2 control-label'
        self.helper.field_class = 'col-lg-4'

        self.helper.layout = Layout(
            Fieldset('Account Modify',
                'irc_name',
                'forum_username',
                Hidden('user_assigned', '{{ user.pk }}'),
                Hidden('forum_id_number', '0'),
                ),

            FormActions(
                Submit('submit', 'Submit', css_class='btn-primary')
                )
         )

    def clean_forum_username(self):
        data = self.cleaned_data['forum_username']
        SLUG = "users/" + data + ".json"
        status_code, response = do_request(SLUG)
        if status_code != 200:
            raise forms.ValidationError("Your username was not"
                                        " found! Please check the"
                                        " the spelling. Also, your"
                                        " forum username is your"
                                        " forum sign in name.")
        elif status_code == 200:
            self.fields['forum_id_number'] = response["User"]["Id"]
        return data

class Employee(models.Model):
    user_assigned = models.ForeignKey(settings.AUTH_USER_MODEL,
            related_name='r_assigned')
    irc_name = models.CharField(max_length="25",
            unique=True)
    forum_id_number = models.BigIntegerField(unique=True)
    forum_username = models.CharField(max_length="50",
            unique=True)

    def __unicode__(self):
        return self.irc_name

1 个回答

1

self.fields['forum_id_number'] 是一个 forms.Field 类的实例。它描述了属性 self.forum_id_number。这一行 self.fields['forum_id_number'] = response["User"]["Id"] 会覆盖这个字段的描述,并把它设置为一个 (Big?)Integer 对象的实例。这个实例当然没有 required 这个属性。

设置 forum_id_number 的“正确”方式是使用 self.forum_id_number = response["User"]["Id"] 或者 self.cleaned_data['forum_id_number'] = response["User"]["Id"]

这里的“正确”加了引号,因为在这种情况下,它其实并不是正确的方式。我们无法知道字段 forum_id_number 是否在任何 clean_FIELD 方法中被清理过,所以你不知道应该设置 self.forum_id_number 还是 self.cleaned_data['forum_id_number']。在 forum_id_number 的情况下,没有安全问题,但任何使用 Firebug 或类似工具的人都可以改变 user_assigned 的值。一般来说,最好把隐藏字段从表单中排除,并在表单的 save 方法中直接设置实例的值。当然,你不能在 save 方法中抛出 ValidationError(其实可以,但会导致 500 Internal Server Error),所以你需要在 clean_forum_username 方法中获取用户 ID:

class AccountForm(forms.ModelForm):
    ....
    def clean_forum_username(self):
        data = self.cleaned_data['forum_username']
        SLUG = "users/" + data + ".json"
        status_code, response = do_request(SLUG)
        if status_code != 200:
            raise forms.ValidationError("Your username was not"
                                        " found! Please check the"
                                        " the spelling. Also, your"
                                        " forum username is your"
                                        " forum sign in name.")
        elif status_code == 200:
            self.response = response
        return data

    def save(self, *args, **kwargs):
        # self.response should be valid, otherwise a `ValidationError` would've been raised
        self.instance.forum_id_number = self.response['User']['Id']
        return super(AccountForm, self).save(*args, **kwargs)

撰写回答