让 Django 仅返回存储为 models.TextField() 的文本的前 50 个字符

Posted

技术标签:

【中文标题】让 Django 仅返回存储为 models.TextField() 的文本的前 50 个字符【英文标题】:Get Django to return only the first 50 characters of text stored as a models.TextField() 【发布时间】:2020-10-18 05:47:11 【问题描述】:

在 Python 速成课程第 18 章中,我们创建了一个学习日志网站。

当我进入我们制作的学习日志网站(通过 localhost:8000)时,我不能只返回 >50 个字符长条目的前 50 个字符。它也不显示省略号,只显示整个条目。

from django.db import models
from django.contrib.auth.models import User

class Topic(models.Model):
    """A topic the user is learning about"""
    text = models.CharField(max_length=200)
    date_added = models.DateTimeField(auto_now_add=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        """Return a string representation of the model."""
        return str(self.text)

class Entry(models.Model):
    """Something specific learned about a topic"""
    topic = models.ForeignKey(Topic, on_delete=models.PROTECT)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = 'entries'

    def __str__(self):
        """Return a string representation of the model."""
        if len(self.text) > 50:
            return f"str(self.text)[:50]..."
        else:
            return f"str(self.text)"

我是否包含if len(self.text) > 50 语句都是一样的。 我的代码与本书的不同之处在于:

    我使用on_delete=models.PROTECT,据我了解,CASCADE 可能会导致奇怪的问题,例如意外得到某些东西 删除了您不打算删除的内容 我在__str__ 定义中使用str(self.text) 而不仅仅是self.text;如果我不这样做,它会引发一个 pylint 错误“值'self.text'是不可订阅的”。我仍然可以在没有 str() 转换的情况下输入 - 但是它仍然不会只显示前 50 个字符。

这与models.TextField() 函数的原因有关吗?我是否应该进行str() 转换才能使self.text 变量“可下标”?

【问题讨论】:

__str__ 方法返回对您没有帮助。它仅用于查看目的,例如,如果您尝试在 python shell 上查看该实例,它会将 self.text 的输出截断为 50 个字符。 所以发送到网页的内容与 str 方法无关,而是它之前的内容,如主题、文本、日期添加变量,对吗? 【参考方案1】:

你也可以这样做:

def __str__(self):
    if self.text[50:]:
        return f"self.text[:50]..."
    else:
        return f"self.text[:50]"

【讨论】:

【参考方案2】:

根据我看到的你可以说

def __str__(self):
    return self.text[:50]

还有

html 表单中调用时可以使用截断词过滤器

您没有显示views.py,而是说您有一个视图可以返回到Entry Class中的所有Entries页面,您碰巧说 % for Entry in Entries % 你只需添加

Entry:text|truncatewords:50

% endfor %

您可以通过The Docs了解更多信息

【讨论】:

【参考方案3】:

在 Django 3.0 中,models.TextField 将返回一个字符串 (str),如果您将其称为 self.textEntry.text。所以你不需要调用str()函数。

如果你想获得前 50 个字符:

def __str__(self):
    return self.text[:50]

在 Python 中,如果您将 [:50] 用于可下标对象,它将返回该对象的前 50 个部分(如果少于 50 个部分,则返回全部)。

希望我的回答对你有所帮助。

【讨论】:

我想这与 Django 过去的工作方式不同?我在 Django 3.0 的更新日志中找不到具体的更改,但在 2 年前的这篇文章中,似乎 Django 不会将其视为字符串。 ***.com/questions/48810094/…我在发布之前尝试了你的建议,它仍然显示了整个文本。我想问题在于这不是发送到网页的内容,而是在 Python shell 中显示的内容,正如其他用户所建议的那样?

以上是关于让 Django 仅返回存储为 models.TextField() 的文本的前 50 个字符的主要内容,如果未能解决你的问题,请参考以下文章

即使数据库将 0 存储为字段值,Django 查询集对象也返回 None 而不是 0

Django聚合:仅求和返回值?

在 Django 模型中保存时区

Django queryset - 在对象上应用过滤器时仅返回匹配的多记录

在 Django 中,仅生成 s3 客户端 generate_presigned_post,内容类型为 mp4 文件上传

request.is_secure() 在双重代理后面返回 False