how to get a record via the ManyToMany link

1

I want to get the email of the restaurant through the order model. How can I do this?

My models.py:

class Order(models.Model):
    cart_meal = models.ManyToManyField(CartMeal, null=True, blank=True)

class CartMeal(models.Model):
    meal = models.ForeignKey(Meal, verbose_name='Meal', on_delete=models.CASCADE)

class Meal(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, null=True)

class Restaurant(models.Model):
    email = models.EmailField()

I need to get to restaurant.email via order. I tried to do it this way, but it doesn’t work: order.cart_meal.model.meal.restaurant.email

I get the order this way views.py

@action(methods=['PUT'], detail=False, url_path='current_customer_cart/add_to_order')
    def add_cart_to_order(self, *args, **kwargs):
        cart = Cart.objects.get(owner=self.request.user.customer)
        cart_meals = CartMeal.objects.filter(cart=cart)
        data = self.request.data

        for restaurant, cart_meals in itertools.groupby(CartMeal.objects.filter(cart=cart).order_by('meal__restaurant'),
                                                        lambda s: s.meal.restaurant):
            order = Order.objects.create(
                customer=self.request.user.customer,
                first_name=data['first_name'],
                last_name=data['last_name'],
                phone=data['phone'],
                address=data.get('address', self.request.user.customer.home_address),
            )
            order.cart_meal.set([cart_meal for cart_meal in cart_meals])
            
            cooking_meal_notification(**restaurant_email=???**)

In calling the last method cooking_meal_notification, I need to get the email of the restaurant

sender.py

def cooking_meal_notification(restaurant_email, meal):
    send_mail(
        'An order has been received',
        meal,
        'kudlasevich.nikita@gmail.com',
        [restaurant_email],
        fail_silently=False,
    )

Answer

There can be multiple Restaurants since an Order can contain multiple meals that are produced by different Restaurants.

You can retrieve a QuerySet of the related Restaurants with:

Restaurant.objects.filter(
    meal__cartmeal__order=order
).distinct()

We can thus retrieve the email addresses of these Restaurants with:

Restaurant.objects.filter(
    meal__cartmeal__order=order
).values_list('email', flat=True).distinct()

This thus produces an iterable of email addresses of the Restaurants related to that order.

You can for example use this to call call a function like cooking_meal_notification:

qs = Restaurant.objects.filter(
    meal__cartmeal__order=order
).values_list('email', flat=True).distinct()

for email in qs:
    cooking_meal_notification(email)

You can also work with the Meals that are “members” of the Order:

qs = Meal.objects.filter(
    cartmeal__order=order
).select_related('restaurant')

for meal in qs:
    cooking_meal_notification(meal.restaurant.email, meal)