Как найти объекты django в отношении manytomany (с помощью сквозной связи)?

Мне нужно найти услуги с ценами для каждого пользователя. Я определил свои модели:

class User(AbstractUser):
    """Default user model."""
    username = None
    email = models.EmailField(unique=True)    
    proposals = models.ManyToManyField(
        Service,
        through=Pricing,
        blank=True)


class Service(models.Model):
    name = models.CharField(max_length=50)

class Pricing(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.PROTECT)
    service = models.ForeignKey(Service, on_delete=models.PROTECT)
    price = models.IntegerField()

В моем шаблоне я могу получить пользователя с ассоциированным предложением с помощью этого цикла for

{% for proposal in object.proposals.all %}
    {{ proposal }}
{% endfor %}

У меня нет цен, а только названия услуг. Что я упускаю?

Вы перечисляете object.pricing_set.all() с:

{% for pricing in object.pricing_set.all %}
    {{ pricing.service }}: {{ pricing.price }}
{% endfor %}

Однако это приведет к проблеме N+1, используя объект Prefetch в представлении, мы можем избежать этого.

Если вы, например, получаете объект User, вы можете предварительно получить pricings и связанные services с помощью:

User.objects.prefetch_related(
    Prefetch('pricing_set', Pricing.objects.select_related('service'))
)

Если вы, таким образом, используете один User с первичным ключом pk, то это может быть реализовано следующим образом:

object = User.objects.prefetch_related(
    Prefetch('pricing_set', Pricing.objects.select_related('service'))
).get(pk=some_pk)

Устанавливает related_name поле внешнего ключа:

class Pricing(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='pricing_instances') # Replace 'pricing_instances' with what makes sense to you
    service = models.ForeignKey(Service, on_delete=models.PROTECT)
    price = models.IntegerField()

Тогда вы можете получить доступ к price следующим образом:

{% for pricing_instance in object.pricing_instances.all %}
    {{ pricing_instance.price }}
{% endfor %}
Вернуться на верх