2013-08-12 28 views
2

我试图从该解决方案here构建一个ModelForm,但是我得到这个错误:“用户”对象有没有属性“得到”

'User' object has no attribute 'get' 

的想法是让ModelForm构造形式当提交用户登录更新的条目。

的models.py是:

class UserDetailsForm(ModelForm): 
    class Meta: 
     model = UserProfile 
     fields = ['mobile_phone'] 

    def __init__(self, *args, **kwargs): 
     self.request = kwargs.pop('request', None) 
     return super(UserDetailsForm, self).__init__(*args, **kwargs) 

    def save(self, *args, **kwargs): 
     kwargs['commit']=False 
     obj = super(UserDetailsForm, self) 
     if self.request: 
      obj.user = UserProfile.objects.get(user=self.request.user) 
     obj.save() 

和我的models.py模型

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    mobile_phone = models.CharField(max_length=30,help_text='Max 30 characters.',blank=True) 
    #have shortened this for simplicity 
    def __unicode__(self): 
     return self.mobile_phone 

在这里的要求是问题的从views.py回溯:

userprofile = UserProfile.objects.get(user=request.user) 
    if request.method == 'POST': 
     form = UserDetailsForm(request.user, request.POST, request.FILES) 
     if form.is_valid(): # it dies here 
      form.save() 
      return HttpResponseRedirect('/members-contact/') 
+0

你为什么要将'obj.user'设置为'UserProfile'的实例? –

+0

'UserProfile'没有'birth_date'字段? – suhailvs

+0

我其实不知道,跳过我可以解决这个问题,通过这里。正如你从模型中看到的,我有一个'OneToOneField'给'User'对象。我试图强行设置。 –

回答

3

你需要一些更简单的东西。都以此为模型的形式:

class UserDetailsForm(ModelForm): 
    class Meta: 
     model = UserProfile 
     fields = ['mobile_phone'] 

在你看来:

from django.core.urlresolvers import reverse_lazy 
from django.views.generic import UpdateView 
from .models import UserDetailsForm, UserProfile 

class UpdateProfile(UpdateView): 
    template_name = 'users/update_profile.html' 
    form_class = UserDetailsForm 
    model = UserProfile 
    success_url = reverse_lazy('home') 

    def get_object(self, queryset=None): 
     '''This loads the profile of the currently logged in user''' 

     return UserProfile.objects.get(user=self.request.user) 

    def form_valid(self, form): 
     '''Here is where you set the user for the new profile''' 

     instance = form.instance # This is the new object being saved 
     instance.user = self.request.user 
     instance.save() 

     return super(UpdateProfile, self).form_valid(form) 

在你urls.py,你需要确保该视图是带一个登录的用户:

from django.contrib.auth.decorators import login_required 
from django.views.generic TemplateView 

from .views import UpdateProfile 

urlpatterns = patterns('', 
    (r'^profile/update/$', login_required(UpdateProfile.as_view())), 
    (r'^$', TemplateView.as_view(template='index.html'), name='home'), 
) 
+0

因此,如果我使用这种方法将更新条目,而不是添加一个新的? –

1
form = UserDetailsForm(request.user, request.POST, request.FILES) 

问题是您将用户对象作为位置参数传递,而您的表单需要第一个位置ar指望成为表格数据。同时,您的表单需要包含请求对象的关键字参数request,但您没有传递这样的参数。改变上述行:

form = UserDetailsForm(request.POST, request.FILES, request=request) 

我看不到你的全视角的功能,但对于简单的形式处理,你可能要考虑使用基于类的视图,基于Django的UpdateView,像布尔汗建议。

+0

这解决了我的错误,但我最终手动处理表单响应,更容易这样做。 –

0

__init__ 代替:

return super(UserDetailsForm, self).__init__(*args, **kwargs) 

尝试:

forms.ModelForm.__init__(self, *args, **kwargs) 

工作对我来说..

0

写这个答案,因为我在一个星期两次被咬这个错误。 来到这个问题,这是没有用的帮助我找出问题。 此代码的问题在于,您已将request.user对象传递给UserDetailsForm的init函数。并且您的init的定义不处理request.user发生的情况。

userprofile = UserProfile.objects.get(user=request.user) 
if request.method == 'POST': 
    ====>form = UserDetailsForm(request.user, request.POST, request.FILES) 
    if form.is_valid(): # it dies here 
     form.save() 
     return HttpResponseRedirect('/members-contact/') 

查看箭头。如果您将其与您的__init__of用户详细信息表单的定义进行比较。你可以看到init不期待这个请求。用户

class UserDetailsForm(ModelForm): 
    class Meta: 
     model = UserProfile 
     fields = ['mobile_phone'] 

    def __init__(self, *args, **kwargs): 
     self.request = kwargs.pop('request', None) 
     return super(UserDetailsForm, self).__init__(*args, **kwargs) 

注意有一个为什么会写初始化一个对象通过正当的理由。

def __init__(self, some_object, *args, **kwargs): 
    super(SomeFormClass, self).__init__(self, *args, **kwargs) 
    self.fields['some_field'].queryset = SomeModel.objects.filter(some_field = some_object) 

还要注意__init__对的ModelForm是默认的DEF已__init __(自我,* ARGS,** kwargs)

这里上面的动态表单初始化是一个很好的例子。

看来,Django是治疗变量传递在这种情况下request.user为some_field并试图呼叫被叫其中“的usermodel”没有get方法。如果你检查堆栈跟踪,你会注意到。下面的堆栈跟踪是一个模拟的例子。

Traceback (most recent call last): 
    File "/home/user/.local/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner 
response = get_response(request) 
    return render(request, self.template_name, context) 
    File "/home/user/.local/lib/python3.5/site- packages/django/shortcuts.py", line 30, in render 
    content = loader.render_to_string(template_name, context, request, using=using) 
--- 
--- 
--- 
packages/django/forms/forms.py", line 297, in non_field_errors 
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield')) 
File "/home/user/.local/lib/python3.5/site-packages/django/forms/forms.py", line 161, in errors 
self.full_clean() 
--- 
--- 
--- 
self._clean_fields() 
File "/home/user/.local/lib/python3.5/site-packages/django/forms/forms.py", line 382, in _clean_fields 
===>value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))<==== 
File "/home/sodara/.local/lib/python3.5/site-packages/django/forms/widgets.py", line 238, in value_from_datadict 
====> return data.get(name) <==== 
AttributeError: 'SomeObject' object has no attribute 'get' 

data.get是返回值的方法调用field.widget.value_from_data_dict的结果...... 如果你注意到,在SomeObject被视为这里whoes get方法被调用的数据。

要回答这个问题,无论是定义初始化处理request.user

def __init__(self, user, *args, **kwargs): 
    super(YourFormClass, self).__init__(*args, **kwargs): 
    self.fields["some_field"].some_attr = user 

或致电形式而不request.user

`form = YourFormClass(request.POST, request.FILES)` 

如果你决定去与选项之一。你必须记得在调用self.fields之前调用super。因为self.fields是由super方法创建的。如果你不会遇到另一个属性错误没有字段名字段。

相关问题