Search code examples
pythondjangolistviewdetailview

How can I link my DetailView and my ListView together?


I'm building a demo-website for a local jewellery store, and I'm trying to create a list of jewellery brands (ListView) and link each to its description (DetailView) in another page. I've spent a solid 15 hours trying to link my ListView and my DetailView together and I haven't fixed anything. These are the views I'm working with:

views

class BrandView(ListView):  
    template_name = 'products.html'
    queryset = models.Brand.objects.order_by('brand_name')
    context_object_name = 'brand_list'

For this first view, I created a template that displays each object from the queryset as a link to its corresponding detail page, which should be represented by the next view:

class TextView(DetailView):
    template_name = 'brands/brand_text.html'    
    context_object_name = 'brand'

    def get(self, request, slug):
        # Grabs the Brand object that owns the given slug
        brand = models.Brand.objects.get(slug = slug)

        # renders self.template_name with the given context and model object
        return render(request, self.template_name, self.context_object_name)

I've also tried writing the last view as a regular function, but this doesn't accomplish anything either:

def text_view(request, slug):
    brand = models.Brand.objects.get(slug = slug)
    return render(request, 'brands/brand_text.html', {'brand': brand,})

Basically, when I click on an object from ListView, the object's slug is added to the url, but the page doesn't change. So how can I successfully link my two views so that the DetailView fetches the information given from the ListView?


Perhaps my templates might prove handy:

templates

brand_text.html

{% block content %}
    <div class= "brands" style="animation: fadein 1.5s 1;">
            <p>
                <a class = "nav_link" href="{% url 'products' %}">Back</a>
            </p>
    </div>

    <div class= "brand_descriptions">
        <p>{{ brand.description }}</p>
    </div>

{% endblock %} 

products.html

{% block content %}
    <div class= "brands" style="animation: fadein 1.5s 1;">
        {% for item in brand_list %}
            <p>
                <a class = "nav_link" href="{% url 'brand_text' item.slug %}">{{ item.brand_name }}</a>
            </p>
        {% endfor %}
    </div>

{% endblock %}

UPDATE 08/02/2016:

URL Patterns

url(r'^products/', BrandView.as_view(), name = 'products'),
url(r'^products/(?P<slug>[-\w]+)', TextView.as_view(), name = 'brand_text'),

(This is my first question, so I apologize if it's too long!)


Solution

  • Your problem is in your url patterns. You have missed out the dollar from the end of your regex. That means that /products/my-slug/ is matched by the regex for BrandView instead or TextView. Change it to:

    url(r'^products/$', BrandView.as_view(), name = 'products'),
    url(r'^products/(?P<slug>[-\w]+)$', TextView.as_view(), name = 'brand_text'),
    

    Note that you can simplify your detail view to:

    class TextView(DetailView):
        template_name = 'brands/brand_text.html'
    

    You don't need to set context_object_name because the default is already 'brand'. It's not usually a good idea to override get for generic class based views - you either lose or have to replicate much of the functionality of the view.