Wednesday, March 20, 2019

Django: View and Details

For this section we are going to add a view and then a details view. In the first view we will see the product names and types. In the details view we will get all the rest of the product information including the discount for members. This will require the following steps:

  1. Create the Product view
  2. Register it with urls.py
  3. Create the product template
  4. Add a menu link in base.html
  5. Create a details view.
  6. Register it in the urls.py
  7. Modify the products template to create a link to details template
  8. Create a details template

Create the Product View

The Product view will look exactly like the ProductType view we did before. I named the function "getProducts." We will get all the products and save them to a products_list.

def getproducts(request):
    products_list=Product.objects.all()
    return render(request, 'techapp/products.html', {'products_list': products_list})

Register the URL

Registering the view in urls.py is also just like before. Here is the urls.py file with the products view added.

from django.urls import path
from . import views

urlpatterns=[
    path('', views.index, name='index'),
    path('gettypes/', views.gettypes, name='types'),
    path('getproducts/', views.getproducts, name='products')
]

Create Product Template

The template will also resemble the one we did for project types. I am only going to display the project name and type on this page. The rest we will save for the details page.

{% extends 'base.html' %}
{% block content %}
<h2>Products</h2>
<table class="table">
  <tr>
      <th>Name</th>
      <th>Type</th>
  </tr>
  {% for p in products_list %}
    <tr>
        <td>{{ p.productname }}</td>
        <td> {{p.producttype }}</td>
    </tr>
    {% endfor %}

</table>
{% endblock %}

Add Menu Link

The Menu link is also essentially the same.

 <ul class="nav navbar-nav">
      <li><a href="{% url 'types' %}">Product Types</a></li>
       <li><a href="{% url 'products' %}">Products</a></li>
               
 </ul>

If we run the server and look at the page we will get this:

Create Details View

It is with the details view that we do something new. In order to get the details for a particular product we need to pass it the id of the Product we are going to display. We pass it as a parameter after the request object. To get the individual product we can use a built in method "get_object_or_404." It takes the primary key as an argument (pk=id). We need to import this method from django.shortcuts.

I have included a lot of extra elements that are not in the assignment, just so you can see them. For one, we will get the discount for members. Also I am going to get a count of how many reviews there are for the project. This creates a more complex context, so we must assemble it before the return statement. Here is the code for the function:

 def productdetails(request, id):
    prod=get_object_or_404(Product, pk=id)
    discount=prod.memberdiscount
    reviews=Review.objects.filter(product=id).count()
    context={
        'prod' : prod,
        'discount' : discount,
        'reviews' : reviews,
    }
    return render(request, 'techapp/proddetails.html', context=context)

Register URL

Registering the details view with urls.py is slightly different in that we must indicate that it receiving the id as integer. We do that by adding "<int:id>" to the usual url. Here is the code for urls.py with the details view added.

 from django.urls import path
from . import views

urlpatterns=[
    path('', views.index, name='index'),
    path('gettypes/', views.gettypes, name='types'),
    path('getproducts/', views.getproducts, name='products'),
    path('productdetails/<int:id>', views.productdetails, name='productdetails'),
]

Modify Products Template

Now we need to add a hyperlink to the Product's template that links it to the details page

Here is the revised hyperlink. Notice how the url is formed and how the id is assigned.

{% extends 'base.html' %}
{% block content %}
<h2>Products</h2>
<table class="table">
  <tr>
      <th>Name</th>
      <th>Type</th>
  </tr>
  {% for p in products_list %}
    <tr>
        <td><a href="{% url 'productdetails' id=p.id %}">{{ p.productname }}</a></td>
        <td> {{p.producttype }}</td>
    </tr>
    {% endfor %}

</table>
{% endblock %}

Create the Details Template

Now we need the details template. We have three data sources passed in our context: prod, which contains all the product information, discount, which contains the discounted amount and reviews, which contains the count of related reviews. We don't have to loop because we are only returning one object. Here is the template code:

{% extends 'base.html' %}
{% block content %}
<h2>{{ prod.productname }}</h2>
<p>Product Type: {{ prod.producttype }} </p>
<p>Added by: {{ prod.user }}</p>
<p>Entry Date: {{ prod.productentrydate }}</p>
<p>URL: {{ prod.producturl }}</p>
<p>Description: {{ prod.productdescription }}</p>
<p>Price: {{ prod.productprice }}</p>
<p>Member discount: {{ discount }}</p>
<p>No. Of Reviews: {{ reviews }}</p>

{% endblock %}

Here are some pictures of the page in action.

Clicking on IPAD

Previous Next

1 comment:

  1. Details View:
    --the line for importing "get_object_or_404" wasn't shown, though the blog text mentions it needs to be done. This my confuse some following the blog post's instructions.

    --When defining the productdetails view in the views.py setup: the return line shows "techapp/proddetails.html" but every other reference is "productdetails". when I encountered this error clicking on the product link on the page, I got an error, and fixed it by adjusting "proddetails" to "productdetails".

    ReplyDelete