【问题标题】:Django - NameError when trying to call model method in viewsDjango - 尝试在视图中调用模型方法时出现 NameError
【发布时间】:2020-07-30 09:52:20
【问题描述】:

我的模型中有一个方法,我想在我的视图中调用它。但是,我收到 NameError 未定义此功能(我已在视图中导入所有模型并且所有迁移都是最新的)。它过去曾用于其他功能。

这是我的模型:

class Song(models.Model):
    """
    fields
    """

    def lyrics_as_list(self):
       return self.lyrics_ru.split()

    def sorted_strings(self, strings, locale=None):
       if locale is None:
           return sorted(strings)
       collator = icu.Collator.createInstance(icu.Locale(locale))
       return sorted(strings, key=collator.getSortKey)

在我看来,我想使用它的相关部分:

lyrics_list = models.Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list() #this is also a method on my model, and it does work
lyrics_sorted = sorted_strings(set(lyrics_list, "ru_RU.UTF8")) #but this one gives me an error

错误:name 'sorted_strings' is not defined

当我将方法移动到我的视图时,它会起作用。但是我必须在几个视图中使用它,所以我试图遵循 DRY 原则,所以让它工作会很棒。

编辑 - sorted_strings 函数的用途: 我的Song 模型包含歌词。我在表格中显示歌词中的所有单词,但我想按字母顺序显示。为了能够对俄语单词进行排序,我需要添加这个功能。

【问题讨论】:

  • 我看不出有充分的理由在 Song 类中包含方法 sorted_strings。不仅命名不好——方法更应该定义动作,名称中有动词,更好的名称是sort_strings——但它没有描述对象Song的任何行为。如果有参数将其保留在 Song 中,最好使用装饰器 @staticmethod 使其成为静态方法。
  • @cezar 谢谢,积分。如果不在我的Song 模型中,那我应该把它放在哪里?
  • 为了给你一个合适的答案,我需要更多地了解你的项目。请尝试反映如何更好地描述您尝试实现的功能。 sorted_strings 这个名字很模糊。什么样的字符串?
  • 我已经编辑了我的问题来解释@cezar 的功能是什么

标签: python python-3.x django django-models django-views


【解决方案1】:

Song中定义的方法sorted strings

class Song(models.Model):
    """
    fields
    """

    def sorted_strings(self, strings, locale=None):
        if locale is None:
            return sorted(strings)
        collator = icu.Collator.createInstance(icu.Locale(locale))
        return sorted(strings, key=collator.getSortKey)

不能这样调用:

sorted_strings(strings, locale)

这显然会导致NameError。它是一种方法,因此您需要在对象上调用它作为该类的实例。

你可能会想试试这个:

Song.sorted_strigns(strings, locale)

但它不会工作。这将导致缺少 1 个必需的位置参数。那就是你必须提供self。不能直接在类上调用。

如果你很好地内省了这个方法,它不会对对象执行任何操作。不使用参数self。您想在不实例化对象的情况下直接在类上调用它。因此你可以使用装饰器@staticmethod:

@staticmethod
def sorted_strings(strings, locale=None):
    if locale is None:
        return sorted(strings)
    collator = icu.Collator.createInstance(icu.Locale(locale))
    return sorted(strings, key=collator.getSortKey)

请注意静态方法不需要传递参数self

现在你的代码应该是这样的:

lyrics_list = Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list()
lyrics_sorted = Song.sorted_strings(set(lyrics_list), "ru_RU.UTF8")

此外,在您的代码示例中,第二行中的括号有错误。

除了静态方法,还有类方法,使用装饰器@classmethod定义。为此,这里我会使用静态方法,但如果有人反对,我准备学习。

静态方法在 Python 中不是很常见,很多人不赞成。
不过,很高兴知道它们的存在以及它们是如何工作的。

【讨论】:

  • 我将该方法移到了另一个名为 methods.py 的文件中,然后将其导入,它正在工作。所以现在我可以将所有我想重用的方法放在这个文件中,而不是特定于Song。感谢您的帮助!
  • @MeL 为此目的创建一个单独的文件是明智的。但是我建议将文件从methods.py 重命名为utils.py。 Django 也使用名称utils,实际上您在该文件中没有方法,但有函数。
【解决方案2】:
lyrics_list = models.Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list()
lyrics_sorted = models.Song.objects.sorted_strings(set(lyrics_list), "ru_RU.UTF8")

Manager的方法只能用Model.objects调用

【讨论】:

  • 添加一些关于如何解决问题的解释
猜你喜欢
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 2019-07-01
  • 2019-09-11
  • 1970-01-01
  • 2015-02-10
相关资源
最近更新 更多