Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django-如何使用两个UserPasseStMixin_Python_Django - Fatal编程技术网

Python Django-如何使用两个UserPasseStMixin

Python Django-如何使用两个UserPasseStMixin,python,django,Python,Django,使用多个UserPasseTestMixin适用于其他视图,但不适用于ProfileCreateView 似乎有一个逻辑错误,我无法理解 views.py class CurrentUser(UserPassesTestMixin): def test_func(self): x = self.request.user.slug print (x) y = self.kwargs['slug'] print (y)

使用多个UserPasseTestMixin适用于其他视图,但不适用于
ProfileCreateView

似乎有一个逻辑错误,我无法理解

views.py

class CurrentUser(UserPassesTestMixin):
    def test_func(self):
        x = self.request.user.slug
        print (x)
        y = self.kwargs['slug']
        print (y)
        if x == y:
            return True
        else:
            if self.request.user.is_authenticated():
                def get_absolute_url(self):
                    return reverse('profile:view_profile', kwargs={ "slug": self.slug })


class ProfileCreate(CurrentUser, UserPassesTestMixin, LoginRequiredMixin, UpdateView):
    model = User
    form_class = ProfileForm
    template_name="profile/profile_new.html"

    def test_func(self):
        x = self.get_object().full_name
        print (x)
        y = ''
        if x == y:
            return True    
        else:
            def get_absolute_url(self):
                return reverse('profile:view_profile', kwargs={ "slug": self.slug })



class ProfileEdit(CurrentUser, UserPassesTestMixin, LoginRequiredMixin, UpdateView):
    model = User
    form_class = ProfileForm
    template_name="profile/profile_new.html"

    def test_func(self):
        x = self.get_object().full_name
        #print (x)
        y = ''
        if x != y:
            return True
        else:
            def get_absolute_url(self):
                return reverse('profile:profile_edit', kwargs={ "slug": self.slug })
CurrentUser
检查用户是否具有编辑配置文件的权限。只有当用户是概要文件的作者时,他才能编辑概要文件。x和y都是这个类打印不同的值x打印loggedin用户的slug值,而y打印url中的slug值这怎么可能是真的

ProfileCreate
类中的
test\u func
检查用户是否已经创建了配置文件,即如果
full\u name
是空字符串,则允许用户创建配置文件。否则将重定向到其他视图

CurrentUser
类适用于其他视图,如
ProfileEdit

总结-- loggedinuser-
localhost:8000/username1

用户将能够访问
localhost:8000/username1/edit/
,但不能访问
localhost:8000/username2/edit/

只有当
全名
为空时,用户才能访问
localhost:8000/username1/create/

如果用户登录为username1,则该用户应无法访问
localhost:8000/username2/create/
——这部分代码不起作用。代码中的逻辑错误是什么?

不能有两个方法调用同一个东西。ProfileCreate中的
测试函数将覆盖CurrentUser中的函数。

您可以通过使用组合而不是继承来实现这一点:

class A(UserPassesTestMixin):
    def test_func(self):
        return True

class B(UserPassesTestMixin):
    def test_func(self):
        return True

class C(UserPassesTestMixin):
    def test_func(self):
        return B.test_func(self) and A.test_func(self) and True
如果你像我一样不喜欢它,你可以做一个可以处理连接的装饰:

def check_all_tests(cls):
    tests = []
    if issubclass(cls, UserPassesTestMixin):
        tests.append(cls.test_func)
    for parent in cls.__bases__:
        if issubclass(parent, UserPassesTestMixin):
            tests.append(parent.test_func)
    cls.test_func = lambda view: all(test(view) for test in tests)
    return cls

@check_all_tests
class C(A, B, UserPassesTestMixin):
    def test_func(self):
        return True
由于我更喜欢一路装饰,我做了一个装饰设计师:

def make_user_test(func):
    def wrapper(cls):
        if issubclass(cls, UserPassesTestMixin):
            old_func = cls.test_func
            cls.test_func = lambda view: old_func(view) and func(view)
            return cls
        else:
            new_cls = type(cls.__name__, (UserPassesTestMixin, *cls.__bases__), cls.__dict__.copy())
            new_cls.test_func = func
            return new_cls
    return wrapper


@make_user_test
def is_creator(view):
    return view.get_object().created_by == view.request.user


@is_creator
@make_user_test(lambda view: view.get_object() != view.request.user.profile.party)  # user cannot delete itself
class PartyDelete(DeleteView):
    model = Party
    success_url = reverse_lazy('party_list')
如果你想要少一点元的东西,我做了一个函数,它将测试列表(函数)作为参数,并返回一个类装饰,通过继承包装原始测试,并添加所有测试的连接:

from inspect import isfunction, signature
from functools import wraps


def user_passes_tests(*args):
    """
    Creates a class decorator that makes decorated class implement UserPassesTestMixin and
    provides implementation using a logical conjunction with all provided functions

    Decorated class must NOT implement UserPassesTestMixin itself
    """
    assert len(args) > 0, 'Provide at least one argument'
    assert all(isfunction(arg) for arg in args), 'All arguments are supposed to be functions'
    assert all(len(signature(f).parameters) == 1 for f in args), 'Functions must expect one and only one argument'

    def decorator(cls):
        assert not issubclass(cls, UserPassesTestMixin), \
            "Do not apply this decorator on UserPassesTestMixin subclass"

        @wraps(cls, updated=())
        class WrapperClass(UserPassesTestMixin, cls):
            def test_func(self):
                return all(func(self) for func in args)

        return WrapperClass

    return decorator

@user_passes_tests(is_creator, is_not_party)
class PartyDelete(DeleteView):
    model = Party
    success_url = reverse_lazy('party_list')

我在
ProfileEdit
类中使用相同的方法,效果很好。