1

Django 1.5 でブログ エンジンを作成し、Django Admin を使用します。ManyToManyField をモデルに追加し、そのフィールドを ModelAdmin のフィールドセットに追加するまで、すべて問題ありませんでしたが、管理ページを読み込もうとすると、この不思議なエラーが発生し始めました。

'NoneType' object has no attribute 'user'

(完全なスタック トレースは後述します。) 応答オブジェクトが突然 None になるのはなぜですか? フィールドセットからフィールドを削除すると、すべてがうまくいきます。

私のモデルは次のようになります (多くのフィールドが削除されています):

class Tag(models.Model):
    name = models.CharField(max_length=30)

class Post(models.Model):
    title = models.CharField(max_length=300)
    tags = models.ManyToManyField(Tag)
    author = models.CharField(max_length=100)

ModelAdmin は次のようになります。

class PostAdmin(admin.ModelAdmin):
    # Order
    fieldsets = (
        ('Content', {
            'fields': ('title', 'tags')
        }),
    )

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        # Pre-fill 'author' with logged in name
        if db_field.name == "author":
            kwargs['initial'] = "%s %s" % (request.user.first_name, request.user.last_name)
            return db_field.formfield(**kwargs)
        return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)

そして、フィールドセットから「タグ」を削除すると、すべてが再び正常になります。単純な Django 管理者の間違いを犯している可能性があります。これまであまり使用したことがありませんでしたが、グーグルで見つけた最高のものは、3 年前に修正されたバグであり、1.5 を実行していると確信しています。 .1.

完全なスタック トレースは次のとおりです。

Internal Server Error: /theadmin/blog/post/1/
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 372, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "C:\Python27\lib\site-packages\django\views\decorators\cache.py", line 89, in _wrapped_view_
unc
    response = view_func(request, *args, **kwargs)
  File "C:\Python27\lib\site-packages\django\contrib\admin\sites.py", line 202, in inner
    return view(request, *args, **kwargs)
  File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 25, in _wrapper
    return bound_func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 21, in bound_func
    return func(self, *args2, **kwargs2)
  File "C:\Python27\lib\site-packages\django\db\transaction.py", line 223, in inner
    return func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 1081, in change_view
    ModelForm = self.get_form(request, obj)
  File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 465, in get_form
    return modelform_factory(self.model, **defaults)
  File "C:\Python27\lib\site-packages\django\forms\models.py", line 424, in modelform_factory
    return type(form)(class_name, (form,), form_class_attrs)
  File "C:\Python27\lib\site-packages\django\forms\models.py", line 212, in __new__
    opts.exclude, opts.widgets, formfield_callback)
  File "C:\Python27\lib\site-packages\django\forms\models.py", line 170, in fields_for_model
    formfield = formfield_callback(f, **kwargs)
  File "E:\Dropbox\PassionateAbout\PassionateAboutJustice\blog\admin.py", line 35, in formfield_for
dbfield
    return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
  File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 125, in formfield_for_
bfield
    related_modeladmin.has_add_permission(request))
  File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 284, in has_add_permis
ion
    return request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
AttributeError: 'NoneType' object has no attribute 'user'
4

1 に答える 1

3

あなたの要求を飲み込む。ここであなたはそれを取ります:

def formfield_for_dbfield(self, db_field, request, **kwargs):

しかし、あなたはそれを伝えません:

return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)

ただし、元のhttps://github.com/django/django/blob/stable/1.5.x/django/contrib/admin/options.py#L88 は次のように定義されています。

def formfield_for_dbfield(self, db_field, **kwargs):

したがって、上書きするときは同じ署名を保持する必要があります。注意してください:オリジナルは次のことを行います:

request = kwargs.pop("request", None)

リクエストにアクセスしたい場合は、「pop()」によって kwargs から削除されるため、同じことをしないでください。削除せずにアクセスするだけ:

request = kwargs['request']

スーパーコールは引き続きリクエストを通過させます。

M2M フィールドでのみ明らかになったのは、現在のユーザーのアクセス許可を検索する要求が必要なため (関連モデルの場合)、CharField は実際には要求を必要としないため、None であることは気にしません。(リクエストが見つからない場合、上記の pop() 呼び出しが実行されます)

最終結果:

def formfield_for_dbfield(self, db_field, **kwargs):
    # Pre-fill 'author' with logged in name
    if db_field.name == "author":
        request = kwargs['request']
        kwargs['initial'] = "%s %s" % (request.user.first_name, request.user.last_name)
        return db_field.formfield(**kwargs)
    return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
于 2013-08-13T20:19:39.773 に答える