django ManyToMany show related objects

南楼画角 提交于 2019-12-24 22:03:16

问题


Searched everywhere but couldn't find anything even though it feels so simple.

So basically i have two classes in my models.py


class Restaurant(models.Model):
    restaurant_title = models.CharField(max_length=30)
    location = CountryField(null=True, blank_label='(select country)')
    first_purchase_discount = models.BooleanField(default=False)
    updated = models.DateTimeField(auto_now=True)
    slug = models.SlugField(max_length=30, unique=True)

def save (self, *args, **kwargs):
    self.slug = slugify(self.restaurant_title)
    super(Restaurant, self).save(*args, **kwargs)

def __str__(self):
    return self.restaurant_title

class Pizza(models.Model):
    pizza_title = models.CharField(max_length=20)
    restaurants = models.ManyToManyField('Restaurant', blank=True) 
    slug = models.SlugField(max_length=20, unique=True)


def save (self, *args, **kwargs):
    self.slug = slugify(self.pizza_title)
    super(pizza, self).save(*args, **kwargs)

def __str__(self):
    return self.pizza_title

now what i did, was register the models in my admin.py. There i created let's say Restaurant Toni and Restaurant Pappo. On the other hand i created the Pizzas: A, B, C and D. Through the ManyToMany relationship i connected Pizza A,B and C to Toni and B, C and D to Pappo.

In my views.py i created a Listview which functions as the Homepage to show where all the Restaurants are being displayed through:

restaurants = Restaurant.objects.all()

To list the Pizzas i created a DetailView. I've created a link in my restaurant_list.html (which functions as the homepage) to access the Pizzas

{% for restaurant in restaurants %} 
    <h2><a href="{% url 'pizza_detail' restaurant.slug %}">{{ restaurant.restaurant_title }}</a></h2>
{% endfor%}

I get the restaurants and each links me to the the Pizzas i associated them to or at least i wish that to happen.

here a clear view at my views.py

class RestaurantListView(ListView):

    model = Restaurant

def get_context_data(self, **kwargs):
    context = super(RestaurantListView, self).get_context_data(**kwargs)
    return context

def home(request):
    template = 'restaurant/restaurant_list.html'
    restaurants = Restaurant.objects.all()
    context = {
        'restaurants': restaurants
    }
    return render(request, template, context)



class PizzaDetailView(DetailView):

    model = Pizza

def get_context_data(self, **kwargs):
    context = super(ShopDetailView, self).get_context_data(**kwargs)
    return context

def pizza_detail(request, slug):
    template = 'restaurant/pizza_detail.html'
    pizzas = Pizza.objects.all()
    context = {
        'pizzas': pizzas,
    }
    return render(request, template, context)

Due to the pizzas = Pizza.objects.all() i obviously get all the Pizzas. But of course i only want the associated ones which means when i click on Toni, i want to see Pizze A,B and C and the related Pizzas for Pappo when i click on "it's" link.

Do i have to change pizzas = Pizza.objects.all() or the for loop in my pizza_detail.html, that for now looks like this?

        {% for pizza in pizzas %}
                        <h1>{{pizza.pizza_title}}</h1>                  
        {% endfor%}

Hope you get my point.

Ps: can you also tell me how to also show the restaurant's name in my pizza_detail.html through which i clicked the link. Thanks alot <3

EDIT

home.urls.py

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^users/', include('django.contrib.auth.urls')),
    url(r'^', include('restaurant.urls')),
]

restaurant.urls.py
urlpatterns = [
    path('', home, name='restaurant_list'),
    path('restaurant/<slug:slug>/', pizza_detail, name='pizza_detail')  
]

回答1:


If you want the Pizzas related to particular restaurant when clicked on them, you should also use the Restaurant model to filter your data

So in views.py

def pizza_detail(request, slug):
    template = 'restaurant/pizza_detail.html'
    restaurant = Restaurant.objects.get(slug=slug)
    pizzas = Pizza.objects.filter(restaurants__in=[restaurant])
    context = {
        'pizzas': pizzas,
        'restaurant': restaurant
    }
    return render(request, template, context)

and in pizza_detail.html

<h1>Restaurant : {{ restaurant.restaurant_title }}</h1> 
{% for pizza in pizzas %}
    <h3>{{pizza.pizza_title}}</h3>                  
{% endfor%}

NOTE : The restaurants__in lookup takes only iterables, hence particular Restaurant object passed as list.




回答2:


Pizza and Restaurant is ManytoMany relation. You can use prefetch_related() for looking pizzas from Restaurant model or vice versa

example: pizzas = Pizza.objects.all().prefetch_related('restaurants')

if you want show restaurant's name in pizza_detail.html. Use example query and change html like this.

{% for pizza in pizzas %}
           {% for restaurant in pizza.restaurants %}   
                 {{restaurant.restaurant_title}}
           {% endfor%}
{% endfor%}


来源:https://stackoverflow.com/questions/51144387/django-manytomany-show-related-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!