3

このコードのどこが間違っているか知っている人はいますか?

def paginated_instance_method(default_page_size=25):
    def wrap(func):
        @functools.wraps(func)
        def inner(self, page=1, page_size=default_page_size, *args, **kwargs):
            objects = func(self=self, *args, **kwargs)
            return _paginate(objects, page, page_size)
        return inner
    return wrap

class Event(object):
    ...
    @paginated_instance_method
    def get_attending_users(self, *args, **kwargs):
        return User.objects.filter(pk__in=self.attending_list)

次のエラーが表示されます。

    Traceback (most recent call last):
      File "<console>", line 1, in <module>
      File "/Users/zarathustra/Virtual_Envs/hinge/hinge_services/hinge/api/decorators.py", line 108, in wrap
        def inner(self, page=1, page_size=default_page_size, *args, **kwargs):
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", line 33, in update_wrapper
        setattr(wrapper, attr, getattr(wrapped, attr))
    AttributeError: 'Event' object has no attribute '__name__'

これがうまくいくと思った理由は、試行錯誤の結果、次のデコレータがクラスメソッドの魅力のように機能するようになったからです。

def paginated_class_method(default_page_size=25):
    def wrap(func):
        @functools.wraps(func)
        def inner(cls, page=1, page_size=default_page_size, *args, **kwargs):
            objects = func(cls=cls, *args, **kwargs)
            return _paginate(objects, page, page_size)
        return inner
    return wrap
4

3 に答える 3

3

paginated_instance_methodデコレータではなく、デコレータを返す関数です。そう

@paginated_instance_method()
def get_attending_users(self, *args, **kwargs):

(括弧に注意してください。)

于 2013-02-26T20:32:18.747 に答える
1

あなたのデコレーターには余分なレベルの間接性があり、物事を台無しにしています。これを行う場合:

@paginated_instance_method
def get_attending_users(self, *args, **kwargs):
    return User.objects.filter(pk__in=self.attending_list)

あなたはこれをやっています:

def get_attending_users(self, *args, **kwargs):
    return User.objects.filter(pk__in=self.attending_list)
get_attending_users = paginated_instance_method(get_attending_users)

それがデコレーターのすることです。が引数としてpaginated_instance_method呼び出されることに注意してください。get_attending_usersつまり、デコレーターでは、引数default_page_sizeが function に設定されますget_attending_users。デコレータは functionwrapを返すため、get_attending_usersその関数に設定されwrapます。

次に、それを呼び出すEvent().get_attending_users()と、 Event インスタンスは wrap(self)どこにありますか。は引数が関数であることを期待しており、その関数をラップする新しい関数を返そうとします。しかし、引数は関数ではなくオブジェクトなので、ラップしようとすると失敗します。selfwrapEventfunctools.wrap

あなたがやろうとしていることはこれだと思います:

@paginated_instance_method()
def get_attending_users(self, *args, **kwargs):
    return User.objects.filter(pk__in=self.attending_list)

つまりpaginated_instance_method、引数を取る必要があります。しかし、その引数のデフォルト値を使用したい場合でも、実際に を呼び出す paginated_instance_method必要があります。それ以外の場合は、メソッドを引数として渡すだけですが、これpaginated_instance_methodは期待しているものではありません。

classmethod で「機能した」理由は、classmethod がクラスを最初の引数として取り、(インスタンスとは異なり) クラス__name__属性を持っているためです。ただし、さらにテストすると、メソッドではなくクラスをラップしているため、本当にやりたいことをしていないことがわかると思います。

于 2013-02-26T20:36:44.607 に答える