簡體   English   中英

'用戶' object 沒有屬性 'get'

[英]'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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM