Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.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-如何使用decorator在基于函数的视图中重用代码_Python_Python 3.x_Django_Django Views_Decorator - Fatal编程技术网

Python Django-如何使用decorator在基于函数的视图中重用代码

Python Django-如何使用decorator在基于函数的视图中重用代码,python,python-3.x,django,django-views,decorator,Python,Python 3.x,Django,Django Views,Decorator,我有一些代码需要在几个视图中重复使用,所以我想创建一个装饰器,这样我就不必复制和粘贴很多行代码 因此,我需要在不同视图中重复使用的代码是: @login_required def add_custom_word_song(request, target_word, source_word, pk): """ Add new word """ if request.method == 'POST':

我有一些代码需要在几个视图中重复使用,所以我想创建一个装饰器,这样我就不必复制和粘贴很多行代码

因此,我需要在不同视图中重复使用的代码是:

@login_required
def add_custom_word_song(request, target_word, source_word, pk):
    """
    Add new word
    """
    if request.method == 'POST':
        form = WordForm(request.POST)
        if form.is_valid():
            deck_name = form.cleaned_data['deck_name']
            source_word = form.cleaned_data['source_word']
            target_word = form.cleaned_data['target_word']
            fluency = form.cleaned_data['fluency']
            user = request.user
            Word.objects.create(user=user, target_word=target_word,
                source_word=source_word, deck_name=deck_name, fluency=fluency)
            return HttpResponseRedirect(reverse('vocab:list'))
    if request.method =="GET":
        user = request.user
        request.session['pk'] = pk
        form = CustomWordForm(initial={'user': user, 'target_word': target_word, 'source_word': source_word, 'deck_name': 'My Words', 'fluency': 0})

    return render(request, 'vocab/add_custom_initial_song.html', {'form': form, 'pk': pk})
对于其他视图,代码中唯一会更改的部分是最后一行中的模板部分。所以我试着把除了最后一行之外的所有东西都放进装饰器里,但后来我得到:

TypeError: add_custom_word() missing 3 required positional arguments: 'target_word', 'source_word', and 'pk'

我尝试了不同的版本,但仍然得到相同的错误。

如果我理解正确,您可能会编写如下代码:

def add_custom_word(request, target_word, second_word, pk):
    ...

@add_custom_word
def add_custom_word_song(request, target_word, second_word, pk):
    return render(request, 'vocab/add_custom_initial_song.html', {'form': form, 'pk': pk})
在这种情况下,如果调用
add\u custom\u word\u song
,则表示:

add_custom_word_song = add_custom_word(add_custom_word_song)
add_custom_word_song()
Python在模块初始化时,第一次通过
add_custom_word_song
作为
add_custom_word
的第一个参数,调用新的
add_custom_word_song

因此,您将得到您所说的错误:
add\u custom\u word()缺少3个必需的位置参数:“target\u word”、“source\u word”和“pk”

如果确实要使用decorator,则需要再次包装它:

def add_custom_word(func):
    def wrapper(request, target_word, second_word, pk):
        ...
        return func(request, target_word, second_word, pk)
    return wrapper

@decorator
def add_custom_word_song(request, target_word, second_word, pk):
    return render(request, 'vocab/add_custom_initial_song.html', {'form': form, 'pk': pk})

但如果您只想更改模板文件,请考虑使用注册表来管理模板内容! 编辑:

最简单的注册表可以像dict:

registry = {
    "song": "vocab/add_custom_initial_song.html",
    "image": "vocab/add_custom_initial_image.html",
    ...
}
可以将某些类型定义为键,然后将模板文件定义为值。因此,您可以按如下方式返回:

def add_custom_word(...):
    ...
    return render(request, registry[return_type], {'form': form, 'pk': pk})
如果您有一些复杂的条件,您可以有一个自定义注册表类,它将始终具有
register
match
方法

class Registry(object):
    def __init__(self):
        self.registry_list = []

    def register(self, conditions, template_file):
        self.registry_list.append([conditions, template_file])

    def match(self, condition):
        for conditions, template_file in self.registry_list:
            if match(condition, conditions):
                return template_file

registry = Registry()
然后可以使用此注册表获取模板文件:

    def add_custom_word(...):
    ...
    return render(request, registry.match(condition), {'form': form, 'pk': pk})

看起来你在试图重新发明轮子。看,我知道基于类的视图,但在本例中似乎没有合适的视图@因此,您可以根据自己的需要进行子类化和调整。无论如何,您共享的代码中不存在错误消息中的函数名。在哪里调用add_custom_word()?这就是我所称的装饰器(与上面的代码相同,只是名称不同),您可以共享您的装饰器代码吗。问题不在上面的代码中,谢谢!请你把你的上一句话再详细一点好吗?@MeL希望这就是你想要的!