在Django中将queryset合并为单个字符串

7 投票
4 回答
14154 浏览
提问于 2025-04-17 16:57

假设我有一个非常简单的模型,就是一串单词:

class WordList(models.Model):
    word = models.CharField(max_length=60)

当用户提交一个表单后,我想要...

  • 随机获取四个单词
  • 把它们组合成一个字符串
  • 确保这个字符串之前没有生成过,如果有,就再来一次
  • 如果没问题,就把它保存到数据库里
  • 把结果返回给用户。

我知道怎么获取四个随机单词:

WordList.objects.order_by('?')[:4]

我知道怎么把这个放到上下文中,并返回给模板,这样我就可以随意处理它,但我不知道怎么在后台完成这些操作,以便在返回给用户之前做好其他事情。最终的字符串应该是这样的:

these-are-my-words

另外,我应该在我的应用程序的哪个地方做这些呢?我之前用PHP的时候,会有一个 functions.php 文件来处理后台的事情,把它和展示部分分开。我看到有些人提到他们使用 functions.py,但我不太确定怎么引入不在同一文件夹里的外部页面,比如和现有的 views.py 不在一个文件夹。如果我这样做:

from functions import myfunc

只有当 functions.py 和我从中导入的文件在同一个文件夹时,它才会工作。

4 个回答

0

最后我找到了解决办法。关键是我没意识到,QuerySet可以像访问Python列表那样直接访问。

dbQuery = WordList.objects.order_by('?')[:4]
result = dbQuery[0]
for word in dbQuery[1:]:
    result = "%s-%s" % (result, word)

我觉得应该有更好的方法来做到这一点。按照建议使用的连接方法并没有奏效,我总是收到一个错误提示,说明它期待一个字符串,尽管所有文档都说这个方法是用来连接列表,而不是字符串,所以我不太明白问题出在哪里。

0

虽然你提供的解决方案“可以用”,但这是一种很PHP的做法。

更符合Django风格的方法是:

在你应用的models.py文件里:

from django.db import models


class Word(models.Model):
    word = models.CharField(max_length=60, blank=False, null=False, unique=True)

    def __unicode__(self):
        return u'%s' % self.word


class RandomWordString(models.Model):
    string = models.CharField(max_length=255, blank=False, null=False, unique=True)

    def __unicode__(self):
        return u'%s' % self.string

    @staticmethod
    def generate(length):
        words = Word.objects.order_by('?')[:(length + 1)]
        possible_word_string = '-'.join(words.values_list('word', flat=True))
        try:
            RandomWordString.objects.get(string=possible_word_string)  # See if we've already generated this sequence
            return RandomWordString.generate(length)  # Call ourselves again if we have
        except RandomWordString.DoesNotExist:
            return possible_word_string  # If we haven't, return the value

    def save(self, *args, **kwargs):
        if not self.string or len(self.string) < 1:
            self.string = RandomWordString.generate(3)
        super(RandomWordString, self).save(*args, **kwargs)

然后,从任何视图或者其他地方:

from words.models import RandomWordString
seq = RandomWordString.generate(3)

因为我们重写了保存功能,所以我们也可以直接这样做:

from words.models import RandomWordString
string = RandomWordString.objects.create()
string.save()

这样所有的逻辑都放在模型里面,这比把逻辑放在视图里要稍微好一点(不过这完全是个人喜好问题)。

除了我提到的内容,你还需要在RandomWordString.generate里加一些逻辑,以确保不会无限循环。

18

要把你的查询结果变成一个字符串,可以使用Python的join函数

your_string = '-'.join([str(i) for i in WordList.objects.order_by('?')[:4]])

我觉得这段代码应该放在你的视图里,而不是直接操作数据库,不过这要看你的应用具体在做什么才好说。(你肯定是把这个字符串传给模板,然后渲染到一个HTML页面上,对吧?)

撰写回答