Bra*_*ano 2 html python django
在 view.py 中,我尝试拆分一个长字符串的属性值。在正常查询中:
someposts = Posts.object.all()[3:5]
Run Code Online (Sandbox Code Playgroud)
应该返回:
<QuerySet [object<first post>, object<second post>]>
Run Code Online (Sandbox Code Playgroud)
然后我按如下方式查询帖子,因为我需要拆分属性值(在此更改之后我收到错误):
someposts = Posts.object.all().values('id', 'title', 'tags')[3:5]
Run Code Online (Sandbox Code Playgroud)
所以它返回类似:
<QuerySet [{'id': 2, 'title': 'first post', 'tags': ' X1, X2, X3,.., X10'}, {'id': 4, 'title': 'second post', 'tags': ' S1, S2, S3,.., S8'}]
Run Code Online (Sandbox Code Playgroud)
但我希望收到tags一份叮咬清单,所以我做了什么:
splited_tags = [v['tags'].split(',') for v in someposts]
for n, i in enumerate(someposts):
someposts[n]['tags'] = splited_tags[n]
Run Code Online (Sandbox Code Playgroud)
结果
<QuerySet [{'id': 2, 'title': 'first post', 'tags': [' X1', 'X2', 'X3',.., X10']}, {'id': 4, 'title': 'second post', 'tags': [' S1', 'S2', 'S3,.., 'S8']}]
Run Code Online (Sandbox Code Playgroud)
因为我要传递someposts给我的模板:
context = {
'someposts':someposts,
}
return render(request, 'app/home.html', context)
Run Code Online (Sandbox Code Playgroud)
在 home.html 中:
{%for post in someposts %}
<a class="avator" href="{% url 'user-post' post.author.username %}"></a>
{ % endfor %}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
未找到参数 '('',)' 的反向 'user-post'
我认为问题是post.author.username因为 post 是一个字符串,它没有.author属性,所以这将被评估为 string_if_invalid ,除非我另外指定,否则它是空字符串 '' 。
你知道如何解决这个错误吗?或者如何拆分查询集中的字符串?
当然,您有多种选择可以解决问题,但为了快速解决您的问题,我将为您提供最简单的解决方案:
您实际上可以对帖子进行注释,以便在每个帖子中都有作者用户名:
from django.db.models import F
Post.objects.annotate(formatted_author=F('author__username')).values('id', 'formatted_author')
Run Code Online (Sandbox Code Playgroud)
这样,您就可以获得撰写帖子的作者的用户名。但是,请小心,如果某些帖子的作者字段中有一些空值,您将在响应中得到None值。
但是,如果您使用Postgres作为数据库,则可以使用Postgres的内置ArrayField功能,并通过以下方式使您的注释更加优雅:
from django.db.models.expressions import Func
from django.db.models import F, Value, TextField
from django.contrib.postgres.fields import ArrayField
formatted_author = F('author__username')
formatted_tags = Func(
F('tags'),
Value(","),
function='regexp_split_to_array', output=ArrayField(TextField())
)
Post.objects \
.annotate(formatted_author=formatted_author, formatted_tags=formatted_tags) \
.values('id', 'formatted_author', 'formatted_tags')
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您还可以节省之前每次迭代时进行 SQL 查询的成本。
如果你没有Postgres数据库,那么我很遗憾地告诉你,你仍然需要在python代码中处理标签,并且我对你当前的实现有一些更好的重构。那么你现在拥有的是:
splited_tags = [v['tags'].split(',') for v in someposts]
for n, i in enumerate(someposts):
someposts[n]['tags'] = splited_tags[n]
Run Code Online (Sandbox Code Playgroud)
而且,我的建议是:
someposts = list(map(lambda somepost: dict(formatted_tags=somepost['tags'].split(','), **somepost), someposts))
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它只需要一次迭代就可以进行新的属性权衡,但这只是我的建议。
当帖子所有者在评论中询问post.author.profile.user.first_name属性时,我想详细说明这一点。post.author.profile.image.url
一般来说,您无法检索这些属性,因为您没有在函数中显式选择它们.values()。.values()将仅检索那些选定的属性。因此,基本上您可以做的就是再次创建F带有注释的变量(为了减少名称长度):
from django.db.models import F
Post.objects.annotate(formatted_author=F('author__username'), formatted_first_name=F('author__profile__user__first_name'), formatted_image=F('author__profile__image')).values('id', 'formatted_author', 'formatted_first_name', 'formatted_image')
Run Code Online (Sandbox Code Playgroud)
正如我的直觉告诉我的那样,实际上post.author.first_name相当于post.author.profile.user.first_name,但如果你有不同的模型结构,我可能是错的。:)
| 归档时间: |
|
| 查看次数: |
7562 次 |
| 最近记录: |