【问题标题】:django NoReverseMatch Error when trying to link template to a view functiondjango NoReverseMatch 尝试将模板链接到视图函数时出错
【发布时间】:2021-03-08 05:42:51
【问题描述】:

我正在尝试将删除对象功能添加到我正在构建的应用程序中,当我尝试在模板中链接到它时,我得到...

NoReverseMatchError 未找到带有参数 '('',)' 的 'delete_player' 的反向操作。尝试了 1 种模式:['game/delete_player/(?P[0-9]+)$']

据我所知,(我认为)我在模板中使用了正确的格式。我认为对象的 id 没有正确传递或根本没有传递存在问题。我一直在寻找 Stack overflow here 和 google 试图找到类似的问题,但我找不到任何与我正在经历的完全匹配的东西。任何建议表示赞赏。

我试图传递给删除函数的模型对象是一个选择字段,看起来像这样。


class Player(models.Model):

    PLAYER_ROLE_CHOICES = (
        (1, 'Quarterback'),
        (2, 'Runningback'),
        (4, 'Widereceiver'),
        (5, 'Tightend'),
        (6, 'Kicker'),
        
    )
    role = models.PositiveSmallIntegerField(choices=PLAYER_ROLE_CHOICES)

模型使用forms.py中的表单

class PlayerForm(forms.Form):

    quarterback_name = forms.CharField(label='Quarterback', max_length=100)
    runningback_name = forms.CharField(label='Runningback', max_length=100)
    widereceiver_name = forms.CharField(label='Widereceiver', max_length=100)
    tightend_name = forms.CharField(label='Tightend', max_length=100)
    kicker_name = forms.CharField(label='Kicker', max_length=100)
    
    def save(self):
        quarterback_name = self.cleaned_data.get('quarterback_name')
        Quarterback.objects.create(name=quarterback_name)
        runningback_name = self.cleaned_data.get('runningback_name')
        Runningback.objects.create(name=runningback_name)
        widereceiver_name = self.cleaned_data.get('widereceiver_name')
        Widereceiver.objects.create(name=widereceiver_name)
        tightend_name = self.cleaned_data.get('tightend_name')
        Tightend.objects.create(name=tightend_name)
        kicker_name = self.cleaned_data.get('kicker_name')
        Kicker.objects.create(name=kicker_name)

我在views.py中的删除对象函数是这样的


def delete_player(request, id):
    player = Player.objects.get(id=id)
    player.delete()
    
    return redirect('show')

urls.py 中的路径是这些...

path('delete_player/<int:id>', views.delete_player, name="delete_player")
path('show/<int:id>', views.show, name="show")

我在我的 html 模板中使用它。

<tr>  
     <td>{{ QB }}  
           <a href="{% url 'delete_player' player.id %}">Delete</a>  
        </td> 
        
    </tr> 

正在渲染的模板称为“show.html”,由views.py中的这个函数渲染

def show(request, id): 
    
    player = Player.objects.get(id=id)

    user = request.user

    if user.is_authenticated: 

        try:
            QB = Quarterback.objects.values_list('name', flat="True")[0]
        except IndexError:
            QB = 'empty'

        try:
            RB = Runningback.objects.values_list('name', flat="True")[0]
        except IndexError:
            RB = 'empty'

        try:     
            WR = Widereceiver.objects.values_list('name', flat="True")[0]
        except IndexError:
            WR = 'empty'

        try:
            TE = Tightend.objects.values_list('name', flat="True")[0]
        except IndexError:
            TE = 'empty' 

        try:    
            K = Kicker.objects.values_list('name', flat="True")[0]
        except IndexError:
            K = 'empty' 

        print(QB)


        context = {
            'QB': QB[0:],
            'RB': RB[0:],
            'WR': WR[0:],
            'TE': TE[0:],
            'K': K[0:],
            'player': player
        }


        return render(request,"game/show.html", context)  

【问题讨论】:

  • 你能分享一下渲染模板的视图吗?可能你没有通过player之类的东西。
  • 当然。让我提出来。
  • 您的context 不包含player... 那么player.id 的值究竟是多少?
  • 啊!这很有意义。好的,我在views.py中将“id”作为参数添加到我的函数中,向def(delete_player)添加了一个名为“player”的实例,并相应地更改了“show”url。我在这里的原始帖子中编辑了我的代码以显示更改。现在它给了我一个 404 错误???

标签: python django django-models django-templates django-urls


【解决方案1】:

urlpattern 需要一个 int:id 但在模板中上下文中没有播放器,因此 player.id 发送一个空值导致错误。

看起来好一点后,我意识到您有一个带有 CHOICES 字段的模型“Player”,但是在表单 save() 方法中,您可以创建各种对象,而实际上这些对象都应该是 Player 对象有一个选择字段来指示他们的角色。

有一刻我认为每个角色都与 Player 模型具有一对一的关系,但从您创建它们的方式来看,它们似乎都是独立的。

所以,根据你的目标,我认为你有多种选择:

  1. 通过一对一的关系将您的玩家与每个角色联系起来,所以 每个玩家可以同时扮演多个角色,并且 一旦你删除了玩家,他的角色也会从 连接表 (on_delete=models.CASCADE)

  2. 仅使用一种模型(播放器),只需使用 CHOICES 字段来区分它们。如果不同的球员类型没有任何独特的特征,这是一个更好的选择(对不起,我不知道关于美式足球的第一件事)。如果你沿着这条路走,那么你可以只使用基于类的 TemplateView 并覆盖 get_context_data 方法以将任何你想要的东西传递给模板(在你的例子中是 Player 模型)。这是一个简单的例子:

    类 HomePageView(TemplateView):

    template_name = 'home.html'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['locations'] = Location.objects.all()
        return context
    

我不知道您的项目,但根据我能收集到的信息,我会向您推荐第二种选择。通过采用它,您基本上可以使用 player.id 导航到任何地方。然后创建一个删除函数将花费您不到一分钟的时间。

我强烈建议您只使用基于类的视图,因为它们非常强大且可重用。他们有一点学习曲线,但随着时间的推移,好处会大大增加。

【讨论】:

  • 感谢您非常详细的分析和回答。我真的对基于类的视图一无所知。你展示的那个例子会进入views.py吗?
  • 是的,它会进入views.py。你可以在这里找到通用视图的一个很好的解释:dj4e.sites.uofmhosting.net/lessons/django_generic
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 2015-12-31
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多