如何按 Django 中 M2M 关系的“through”table 中的字段进行排序?
How to order by a field from the `through` table for a M2M relationship in Django?
我有两个模型 - Note 和 Pinboard - 在 Django 应用程序中具有多对多关系。这两个模型通过另一个模型相关 - Pin - 因此我可以存储有关关系的其他信息。
我想在 Pinboard 的 DetailView
中显示相关的 Note 实例。那不是问题。但是我想 prefetch 注释,并且 order 它们在 through
table 的 position
字段上].
关于如何存档的任何提示(预取 + 在第三个 table 上排序)?
例子
这就是我目前所拥有的……它在某种意义上是有效的,我不必查询每个条目,但我发现无法订购 Note position
个实例,无需对每个实例进行更多查询。
型号
from django.db import models
class Note(models.Model):
title = models.CharField(max_lenght=200)
content = models.TextField()
class Pinboard(models.Model):
title = models.CharField(max_lenght=200)
notes = models.ManyToManyField(
Note, blank=True, related_name='pinboards', through='Pin'
)
class Pin(models.Model):
class Meta:
ordering = ['position', ]
get_latest_by = 'position'
pinboard = models.ForeignKey(Pinboard, related_name='note_pins')
note = models.ForeignKey(Note, related_name='pinboard_pins')
position = models.PositiveSmallIntegerField(default=0)
查看
from django.views.generic import DetailView
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related('notes')
模板
{% extends 'base.html' %}
{% block content %}
<h1>{{ pinboard.title }}</h1>
{% if pinboard.notes.all.exists %}
<ol>
{% for note in pinboard.notes %}
<li>{{ note.title }}</li>
{% endfor %}
</ol>
{% else %}
<p>Nothing here yet…</p>
{% endif %}
{% endblock content %}
我建议你使用 Prefetch
object。
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related(
Prefetch(
'notes',
Note.objects.order_by('pinboard_pins__position'),
)
)
顺便说一下,您根本不需要在 DetailView
上使用 prefetch_related
,因为它会产生相同数量的查询。
此外,since you're already fetching the pinboard.notes
我建议您使用 {% if pinboard.notes.all %}
而不是 {% if pinboard.notes.all.exists %}
。
我有两个模型 - Note 和 Pinboard - 在 Django 应用程序中具有多对多关系。这两个模型通过另一个模型相关 - Pin - 因此我可以存储有关关系的其他信息。
我想在 Pinboard 的 DetailView
中显示相关的 Note 实例。那不是问题。但是我想 prefetch 注释,并且 order 它们在 through
table 的 position
字段上].
关于如何存档的任何提示(预取 + 在第三个 table 上排序)?
例子
这就是我目前所拥有的……它在某种意义上是有效的,我不必查询每个条目,但我发现无法订购 Note position
个实例,无需对每个实例进行更多查询。
型号
from django.db import models
class Note(models.Model):
title = models.CharField(max_lenght=200)
content = models.TextField()
class Pinboard(models.Model):
title = models.CharField(max_lenght=200)
notes = models.ManyToManyField(
Note, blank=True, related_name='pinboards', through='Pin'
)
class Pin(models.Model):
class Meta:
ordering = ['position', ]
get_latest_by = 'position'
pinboard = models.ForeignKey(Pinboard, related_name='note_pins')
note = models.ForeignKey(Note, related_name='pinboard_pins')
position = models.PositiveSmallIntegerField(default=0)
查看
from django.views.generic import DetailView
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related('notes')
模板
{% extends 'base.html' %}
{% block content %}
<h1>{{ pinboard.title }}</h1>
{% if pinboard.notes.all.exists %}
<ol>
{% for note in pinboard.notes %}
<li>{{ note.title }}</li>
{% endfor %}
</ol>
{% else %}
<p>Nothing here yet…</p>
{% endif %}
{% endblock content %}
我建议你使用 Prefetch
object。
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related(
Prefetch(
'notes',
Note.objects.order_by('pinboard_pins__position'),
)
)
顺便说一下,您根本不需要在 DetailView
上使用 prefetch_related
,因为它会产生相同数量的查询。
此外,since you're already fetching the pinboard.notes
我建议您使用 {% if pinboard.notes.all %}
而不是 {% if pinboard.notes.all.exists %}
。