如何解决Django - 如何使用装饰器在基于函数的视图中重用代码
我有一些代码必须在多个视图中重复使用,所以我想创建一个装饰器,这样我就不必复制和粘贴多行代码。
所以我需要在不同视图中重用的代码是:
@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,pk):
return render(request,'vocab/add_custom_initial_song.html',{'form': form,'pk': pk})
在这种情况下,如果您调用 add_custom_word_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_custom_word() missing 3 required positional arguments: 'target_word','source_word',and 'pk'
如果你真的要使用装饰器,你需要重新包装它:
def add_custom_word(func):
def wrapper(request,pk):
...
return func(request,pk)
return wrapper
@decorator
def add_custom_word_song(request,'pk': pk})
但如果只想更改模板文件,可以考虑使用注册表来管理模板内容!
编辑:
一个最简单的注册表就像一个字典:
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],'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),'pk': pk})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。