问题
I have a queryset and I want to apply function (port_to_app) to its field (dst_port). And then access it from template. How do I do that? I've read about filters and tags, but can't understand the way they work.
models.py
class FlowQuerySets(models.QuerySet):
def top_app(self):
return self.values('dst_port')\
.annotate(traffic=Sum('bytes')).order_by('-traffic')[:10]
class Flow(models.Model):
id = models.BigIntegerField(primary_key = True)
ip_src = models.CharField(max_length=15)
ip_dst = models.CharField(max_length=15)
src_port = models.IntegerField()
dst_port = models.IntegerField()
objects = FlowQuerySets.as_manager()
def port_to_app(self):
"returns application instead of port using socket module"
import socket
if self.dst_port:
return socket.getservbyport(int(dst_port))
views.py
def top_conversations_app(request):
top_app = Flow.objects.top_app()
return render (request, 'flow/home.html', {'top_app': top_app})
home.html
{% for p in top_app %}
{{ p.dst_port }}
{{ p.traffic | filesizeformat}}
{% endfor %}
回答1:
The port_to_app on the model object is not available because top_app uses .values and thus returns a list of dicts. Try adjusting your QuerySet to something like this instead:
class FlowQuerySets(models.QuerySet):
def top_app(self):
import socket
for obj in self.values('dst_port')\
.annotate(traffic=Sum('bytes')).order_by('-traffic')[:10]:
if obj['dst_port']:
obj['dst_port'] = socket.getservbyport(int(obj['dst_port']))
yield obj
回答2:
well, you can mark is as a property
@property
def port_app(self):
"returns application instead of port using socket module"
import socket
if self.dst_port:
return socket.getservbyport(int(dst_port))
and then in your template you can access it as any other model property
{% for p in top_app %}
{{ p.port_app }}
{% endfor %}
来源:https://stackoverflow.com/questions/34929761/django-apply-function-to-queryset