Django 中的问题计数模板中的字符串
Issue in Django count string in a template
我在尝试计数时遇到问题。
希望你能帮助我。
在模板中,如果我插入 {{ message.count }} 不会发生,因为消息是一个字符串。如果我插入 {% load inbox %} {% inbox_count as message %} 它 returns 所有未读消息,但我需要获取给定用户发送的未读消息,在我的例子中,候选人到工作岗位。
我该怎么做?
#models.py
class CandidateToJob(models.Model):
job = models.ForeignKey(Job, related_name='applied_to')
candidate = models.ForeignKey(Candidate, related_name='from_user')
STATUS_CHOICES = (
('0', 'New'),
('1', 'Not approved'),
('2', 'Approved')
)
status = models.CharField(max_length=2, choices=STATUS_CHOICES)
def __unicode__(self):
return self.candidate.user.get_full_name()
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
class MessageManager(models.Manager):
def inbox_for(self, user):
"""
Returns all messages that were received by the given user
"""
return self.filter(
recipient=user
)
class Message(models.Model):
"""
A private message from user to user
"""
body = models.TextField(_("Mensagem"))
sender = models.ForeignKey(AUTH_USER_MODEL, related_name='sent_messages')
recipient = models.ForeignKey(AUTH_USER_MODEL, related_name='received_messages', null=False, blank=True)
sent_at = models.DateTimeField(null=True, blank=True)
read_at = models.DateTimeField(_("read at"), null=True, blank=True)
objects = MessageManager()
def __unicode__(self):
return self.sender.username
def inbox_count_for(user):
"""
returns the number of unread messages for the given user but does not
mark them seen
"""
return Message.objects.filter(recipient=user, read_at__isnull=True).count()
景色
#views.py
class Screening(generic.DetailView):
model = Job
template_name = 'dashboard/screening.html'
def get_context_data(self, **kwargs):
context = super(Screening, self).get_context_data(**kwargs)
context['candidate_list'] = self.object.applied_to.all().order_by('candidate')
context['messages_received'] = Message.objects.inbox_for(self.request.user)
return context
模板
#template.html
{% for candidate in candidate_list %}
{{ candidate.get_full_name }}
{{ candidate.candidate.city }}
{% for message in messages_received %}
{% if candidate.candidate.user == message.sender %}
{{ message }}
{% endif %}
{% endfor %}
{% endfor %}
模板标签
#inbox.py
from django.template import Library, Node, TemplateSyntaxError
class InboxOutput(Node):
def __init__(self, varname=None):
self.varname = varname
def render(self, context):
try:
user = context['user']
count = user.received_messages.filter(read_at__isnull=True).count()
except(KeyError, AttributeError):
count = ''
if self.varname is not None:
context[self.varname] = count
return ""
else:
return "%s" % (count)
def do_print_inbox_count(parser, token):
"""
A templatetag to show the unread-count for a logged in user.
Returns the number of unread messages in the user's inbox.
Usage::
{% load inbox %}
{% inbox_count %}
{# or assign the value to a variable: #}
{% inbox_count as my_var %}
{{ my_var }}
"""
bits = token.contents.split()
if len(bits) > 1:
if len(bits) != 3:
raise TemplateSyntaxError("inbox_count tag takes either no arguments or exactly two arguments")
if bits[1] != 'as':
raise TemplateSyntaxError("first argument to inbox_count tag must be 'as'")
return InboxOutput(bits[2])
else:
return InboxOutput()
register = Library()
register.tag('inbox_count', do_print_inbox_count)
您无法在模板语言中执行您想要的复杂逻辑。我喜欢这个事实,因为它有助于防止您将业务逻辑引入模板(它不属于的地方)。
您应该能够通过以下方式完成您想要的:
from django.db.models import Count
class Screening(generic.DetailView):
model = Job
template_name = 'dashboard/screening.html'
def get_context_data(self, **kwargs):
context = super(Screening, self).get_context_data(**kwargs)
# Fetch the sender_id for each unread message.
# Count the number of times that the sender_id was included.
# Then convert the list of tuples into a dictionary for quick lookup.
sent_messages = dict(self.request.user.received_messages.filter(
read_at__isnull=True
).values('sender_id').annotate(
messages_sent=Count('user_id')
).values_list('sender_id', 'messages_sent'))
candidates = []
for candidate in self.object.applied_to.all().order_by('candidate'):
candidate.messages_sent = sent_messages.get(candidate.id, 0)
candidates.append(candidate)
context['candidate_list'] = candidates
return context
然后在您的模板中使用:
{% for candidate in candidate_list %}
{{ candidate.get_full_name }}
{{ candidate.candidate.city }}
{{ candidate.messages_sent }}
{% endfor %}
这种方法的缺点是您无法访问单独的消息。
编辑:您可以阅读有关注释和聚合的内容 here。那里有更多信息。
我在尝试计数时遇到问题。 希望你能帮助我。
在模板中,如果我插入 {{ message.count }} 不会发生,因为消息是一个字符串。如果我插入 {% load inbox %} {% inbox_count as message %} 它 returns 所有未读消息,但我需要获取给定用户发送的未读消息,在我的例子中,候选人到工作岗位。
我该怎么做?
#models.py
class CandidateToJob(models.Model):
job = models.ForeignKey(Job, related_name='applied_to')
candidate = models.ForeignKey(Candidate, related_name='from_user')
STATUS_CHOICES = (
('0', 'New'),
('1', 'Not approved'),
('2', 'Approved')
)
status = models.CharField(max_length=2, choices=STATUS_CHOICES)
def __unicode__(self):
return self.candidate.user.get_full_name()
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
class MessageManager(models.Manager):
def inbox_for(self, user):
"""
Returns all messages that were received by the given user
"""
return self.filter(
recipient=user
)
class Message(models.Model):
"""
A private message from user to user
"""
body = models.TextField(_("Mensagem"))
sender = models.ForeignKey(AUTH_USER_MODEL, related_name='sent_messages')
recipient = models.ForeignKey(AUTH_USER_MODEL, related_name='received_messages', null=False, blank=True)
sent_at = models.DateTimeField(null=True, blank=True)
read_at = models.DateTimeField(_("read at"), null=True, blank=True)
objects = MessageManager()
def __unicode__(self):
return self.sender.username
def inbox_count_for(user):
"""
returns the number of unread messages for the given user but does not
mark them seen
"""
return Message.objects.filter(recipient=user, read_at__isnull=True).count()
景色
#views.py
class Screening(generic.DetailView):
model = Job
template_name = 'dashboard/screening.html'
def get_context_data(self, **kwargs):
context = super(Screening, self).get_context_data(**kwargs)
context['candidate_list'] = self.object.applied_to.all().order_by('candidate')
context['messages_received'] = Message.objects.inbox_for(self.request.user)
return context
模板
#template.html
{% for candidate in candidate_list %}
{{ candidate.get_full_name }}
{{ candidate.candidate.city }}
{% for message in messages_received %}
{% if candidate.candidate.user == message.sender %}
{{ message }}
{% endif %}
{% endfor %}
{% endfor %}
模板标签
#inbox.py
from django.template import Library, Node, TemplateSyntaxError
class InboxOutput(Node):
def __init__(self, varname=None):
self.varname = varname
def render(self, context):
try:
user = context['user']
count = user.received_messages.filter(read_at__isnull=True).count()
except(KeyError, AttributeError):
count = ''
if self.varname is not None:
context[self.varname] = count
return ""
else:
return "%s" % (count)
def do_print_inbox_count(parser, token):
"""
A templatetag to show the unread-count for a logged in user.
Returns the number of unread messages in the user's inbox.
Usage::
{% load inbox %}
{% inbox_count %}
{# or assign the value to a variable: #}
{% inbox_count as my_var %}
{{ my_var }}
"""
bits = token.contents.split()
if len(bits) > 1:
if len(bits) != 3:
raise TemplateSyntaxError("inbox_count tag takes either no arguments or exactly two arguments")
if bits[1] != 'as':
raise TemplateSyntaxError("first argument to inbox_count tag must be 'as'")
return InboxOutput(bits[2])
else:
return InboxOutput()
register = Library()
register.tag('inbox_count', do_print_inbox_count)
您无法在模板语言中执行您想要的复杂逻辑。我喜欢这个事实,因为它有助于防止您将业务逻辑引入模板(它不属于的地方)。
您应该能够通过以下方式完成您想要的:
from django.db.models import Count
class Screening(generic.DetailView):
model = Job
template_name = 'dashboard/screening.html'
def get_context_data(self, **kwargs):
context = super(Screening, self).get_context_data(**kwargs)
# Fetch the sender_id for each unread message.
# Count the number of times that the sender_id was included.
# Then convert the list of tuples into a dictionary for quick lookup.
sent_messages = dict(self.request.user.received_messages.filter(
read_at__isnull=True
).values('sender_id').annotate(
messages_sent=Count('user_id')
).values_list('sender_id', 'messages_sent'))
candidates = []
for candidate in self.object.applied_to.all().order_by('candidate'):
candidate.messages_sent = sent_messages.get(candidate.id, 0)
candidates.append(candidate)
context['candidate_list'] = candidates
return context
然后在您的模板中使用:
{% for candidate in candidate_list %}
{{ candidate.get_full_name }}
{{ candidate.candidate.city }}
{{ candidate.messages_sent }}
{% endfor %}
这种方法的缺点是您无法访问单独的消息。
编辑:您可以阅读有关注释和聚合的内容 here。那里有更多信息。