Django自定义模板过滤器——如何提及用户和类别
Django Custom Template Filter - How To Mention Users And Categories
我正在制作一个社交网站,我希望能够使用 # 符号来提及用户或类别。 (示例:#User #Category #Other Category)。使用模板过滤器,我想首先找到字符串中的所有#,然后获取它后面的单词。然后我会检查类别的模型:
class Category(models.Model):
name = models.CharField(max_length=250, unique=True)
category_detail = models.TextField(max_length=1250, default='No information is known on this category.')
如果它与类别不匹配,我会检查# 后面的词是否是用户。如果它是一个类别,我想 link 使用 <a>
标签,如果它是用户,我也想 link 使用 <a>
标签。
urls:
urlpatterns = [
path('u/@<str:username>', UserPostListView.as_view(), name='user-posts'), # User Profile Link. Link This If After The # The Word Is A User
path('c/<str:cats>/', views.category_view, name='category-detail'), # View Category Link. Link This If After The # The Word Is A Category
]
用法:
回到这个例子,假设我有这样的评论:
这太棒了post! #some_user #类别#other_category
在我的模板中,我将其呈现为:
{{ comment.text|safe|filter_to_parse }}
我想要模板过滤器 filter_to_parse
到 return:
This is such a great post! <a href="/u/@some_user">#some_user</a> <a href="/c/category">#category</a> <a href="/c/other_category">#other_category</a>
那么我如何在 Django 中制作模板过滤器来做到这一点?
我发现了一些可以帮助我做到这一点的东西:
- How to mention users using @ in django
- https://pypi.org/project/django-mentions/
但是这些 link 中的代码不起作用。谢谢。
编辑 2:
好的,感谢@flunder,我添加了 mark_safe 并尝试调试过滤器。这是我目前的工作代码:
from django import template
from django.template.defaultfilters import stringfilter
from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username=stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
res = res + i + ' '
return mark_safe(res)
except User.DoesNotExist:
return value
else:
return value
这有效,并且在模板中它有一个 link 到用户配置文件,但缺少其余评论。示例:“@da 嗨!”变成了“@da”,没有嗨!这是因为它 returns res,它是标签和 space,所以我也需要帮助 return 阅读其余的评论。
此代码的另一个问题是,如果您提到多个用户,如@da @user2,那么只有第一个用户成为 url,其余的只是文本。
来自提到的评论:
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
res = ""
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
res = res + i + ' '
return res
您是否加载了标签并使用了提及过滤器?
正确答案是:
from django.utils.safestring import mark_safe
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
res = ""
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
res = res + i + ' '
return mark_save(res)
mark_save:明确地将字符串标记为安全的(HTML)输出目的。返回的对象可以在任何适合字符串的地方使用。
这是完全未经测试的代码,但为了让您继续:
def 提及(原件):
listAts = 列表()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
不是完整的功能代码,但可以帮助您入门:
def mention(value):
listOfAts = list()
listOfSpaces = list()
lastPosOfAt = 0
while True:
at = value.find("@", lastPosOfAt+1)
if at != -1:
lastPosOfAt = at
listofAts.append(at)
else:
break
然后你有一个列表,其中包含 'value' 中“@”的所有位置。
我正在制作一个社交网站,我希望能够使用 # 符号来提及用户或类别。 (示例:#User #Category #Other Category)。使用模板过滤器,我想首先找到字符串中的所有#,然后获取它后面的单词。然后我会检查类别的模型:
class Category(models.Model):
name = models.CharField(max_length=250, unique=True)
category_detail = models.TextField(max_length=1250, default='No information is known on this category.')
如果它与类别不匹配,我会检查# 后面的词是否是用户。如果它是一个类别,我想 link 使用 <a>
标签,如果它是用户,我也想 link 使用 <a>
标签。
urls:
urlpatterns = [
path('u/@<str:username>', UserPostListView.as_view(), name='user-posts'), # User Profile Link. Link This If After The # The Word Is A User
path('c/<str:cats>/', views.category_view, name='category-detail'), # View Category Link. Link This If After The # The Word Is A Category
]
用法: 回到这个例子,假设我有这样的评论:
这太棒了post! #some_user #类别#other_category
在我的模板中,我将其呈现为:
{{ comment.text|safe|filter_to_parse }}
我想要模板过滤器 filter_to_parse
到 return:
This is such a great post! <a href="/u/@some_user">#some_user</a> <a href="/c/category">#category</a> <a href="/c/other_category">#other_category</a>
那么我如何在 Django 中制作模板过滤器来做到这一点?
我发现了一些可以帮助我做到这一点的东西:
- How to mention users using @ in django
- https://pypi.org/project/django-mentions/
但是这些 link 中的代码不起作用。谢谢。
编辑 2: 好的,感谢@flunder,我添加了 mark_safe 并尝试调试过滤器。这是我目前的工作代码:
from django import template
from django.template.defaultfilters import stringfilter
from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username=stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
res = res + i + ' '
return mark_safe(res)
except User.DoesNotExist:
return value
else:
return value
这有效,并且在模板中它有一个 link 到用户配置文件,但缺少其余评论。示例:“@da 嗨!”变成了“@da”,没有嗨!这是因为它 returns res,它是标签和 space,所以我也需要帮助 return 阅读其余的评论。
此代码的另一个问题是,如果您提到多个用户,如@da @user2,那么只有第一个用户成为 url,其余的只是文本。
来自提到的评论:
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
res = ""
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
res = res + i + ' '
return res
您是否加载了标签并使用了提及过滤器?
正确答案是:
from django.utils.safestring import mark_safe
@register.filter(name='mention', is_safe=True)
@stringfilter
def mention(value):
res = ""
my_list = value.split()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
res = res + i + ' '
return mark_save(res)
mark_save:明确地将字符串标记为安全的(HTML)输出目的。返回的对象可以在任何适合字符串的地方使用。
这是完全未经测试的代码,但为了让您继续: def 提及(原件): listAts = 列表()
for i in my_list:
if i[0] == '@':
try:
stng = i[1:]
user = User.objects.get(username = stng)
if user:
profile_link = user.userprofile.get_absolute_url()
i = f"<a href='{profile_link}'>{i}</a>"
except User.DoesNotExist:
print("Could not get the data")
不是完整的功能代码,但可以帮助您入门:
def mention(value):
listOfAts = list()
listOfSpaces = list()
lastPosOfAt = 0
while True:
at = value.find("@", lastPosOfAt+1)
if at != -1:
lastPosOfAt = at
listofAts.append(at)
else:
break
然后你有一个列表,其中包含 'value' 中“@”的所有位置。