[英]'User' object has no attribute 'get'
我試圖從這里的這個解決方案構建一個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 中的 model 是
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/')
寫這個答案是因為我在一周內被這個錯誤咬了兩次。 來到這個問題,並沒有幫助我解決問題。 這段代碼的問題在於您已將 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 不期望那個 request.user
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)
請注意,編寫 init 以傳入對象是有正當理由的。
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__ 的默認定義具有 __init__(self, *args, **kwargs)
上面的動態表單初始化就是一個很好的例子。
在這種情況下,django 似乎將傳入的變量處理為 request.user 作為 some_field 並試圖調用一個名為 get 的方法,而“UserModel”沒有。 如果您檢查堆棧跟蹤,您會注意到。 下面的堆棧跟蹤是一個模擬示例。
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 被視為正在調用 get 方法的數據。
要回答這個問題,要么定義 init 來處理 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 方法創建的。 如果你不這樣做,你會遇到另一個沒有字段名為字段的屬性錯誤。
編輯
Django 提供了一個方便的方法get_form_kwargs
用於將屬性添加到從django.views.generic.edit.ModelFormMixin
繼承的表單視圖的 init 中,例如FormView
。
class MyFormView(FormView):
form_class = MyModelFormClass
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
class MyModelFormClass(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user') # Important to do this
# If you dont, calling super will fail because the init does
# not expect, user among the fields.
super().__init__(*args, **kwargs)
self.fields['some_field'].queryset = SomeModel.objects.filter(user=user)
你需要一些更簡單的東西。 將此作為您的模型形式:
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'),
)
form = UserDetailsForm(request.user, request.POST, request.FILES)
問題是您將用戶對象作為位置參數傳遞,而您的表單期望第一個位置參數是表單數據。 同時,您的表單需要一個包含請求對象的關鍵字參數request
,但您沒有傳遞這樣的參數。 將上面的行更改為:
form = UserDetailsForm(request.POST, request.FILES, request=request)
我看不到您的完整視圖功能,但對於簡單的表單處理,您可能需要考慮使用基於 Django 的UpdateView
基於類的視圖,就像 Burhan 建議的那樣。
在__init__
而不是:
return super(UserDetailsForm, self).__init__(*args, **kwargs)
嘗試:
forms.ModelForm.__init__(self, *args, **kwargs)
它對我有用..
對於在這里使用get
方法的訪問者:
from django.contrib.auth.models import User
u = User.objects.all()[0]
print(u.get('username'))
# switch the line above to below
print(getattr(u, 'username'))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.