4

ここ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/')
4

4 に答える 4

4

この回答を書いているのは、このエラーで 1 週間に 2 回噛まれたからです。この質問に来ましたが、問題を理解するのに役に立ちませんでした。このコードの問題は、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 として扱っており、「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 は 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)`

オプション1を使用することにした場合。self.fields を呼び出す前に super を呼び出すことを忘れないでください。self.fields は super メソッドによって作成されるためです。そうしないと、fields という名前のフィールドがないという別の属性エラーが発生します。

編集

Django は、などget_form_kwargsから継承するフォーム ビューの init に属性を追加するための便利な方法を提供します。django.views.generic.edit.ModelFormMixinFormView

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)
于 2017-05-05T11:50:49.797 に答える
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'),
)
于 2013-08-12T10:32:51.277 に答える
0

__init__ 代わりに:

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

試す:

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

わたしにはできる..

于 2014-02-02T10:15:19.813 に答える