STAY INFORMED
following content serves as a personal note and may lack complete accuracy or certainty.

Minimal-Mistakes instruction
Useful vscode Shortcut Keys
Unix Commands
npm Commands
Vim Commands
Git Note
Useful Figma Shortcut Keys

3 minute read

E-Commerce Website Project_1 E-Commerce Website Project_2 E-Commerce Website Project_4 E-Commerce Website Project_5

Views

Item List View

# views.py 
from .models import Item

def item_list(request):
    items = Item.objects.all()
    context = {"items": items}
    return render(request, "ecommerce/item_list.html", context)
<!-- item_list.html -->
{% extends "ecommerce_base/base.html" %}

{% block content %}
<h1>item list</h1>
{% for item in items %}
<a href="{% url 'item-detail' item.id %}"><p>{{item.name}} detail</p></a>
{% endfor %}
{% endblock content %}

des1

Item Detail View

url pattern be like

# urls.py
urlpatterns = [
    path("", views.index, name='index'),
    path("items/", views.item_list, name='item-list'),
    path("items/<int:item_id>/", views.item_detail, name='item-detail'),
    path("profile/", views.user_profile, name='user-profile'),
]

Because to display one specific item, need item’s id. Also each item has reviews, so import Review model and get reviews depending on the item_id.

# views.py 

def item_detail(request, item_id):
    item = Item.objects.get(id=item_id)
    reviews = Review.objects.filter(item=item)
    context = {"item": item,
                "reviews": reviews
            }
    return render(request, "ecommerce/item_detail.html", context)

the ‘item_id’ parameter is used for “/".

<!-- item_detail.html -->

{% extends "ecommerce_base/base.html" %}

{% block content %}
<h1>{{item.name}}</h1>
<h1>{{item.category}}</h1>
<img src="{{item.image.url}}" alt="itemImg">
{% if reviews %}
<ul>
    {% for review in reviews %}
        <li>
            <strong>Rate:</strong> {{ review.rate }}<br>
            <strong>Comment:</strong> {{ review.comment }}<br>
            <strong>Date:</strong> {{ review.createdAt }}
        </li>
    {% endfor %}
</ul>
{% else %}
<p>No reviews available for this item.</p>
{% endif %}
{% endblock content %}

des2

Profile View

For now, I will make profile page displays logged in user’s infos and design it later.

# views.py

def user_profile(request, user_id):
    user = get_object_or_404(User, id=user_id)
    reviews = Review.objects.filter(user=user)
    orders = Order.objects.filter(user=user)
    context = {
        'user': user,
        'reviews': reviews,
        "orders": orders
    }
    return render(request, "ecommerce/user_profile.html", context)

des3

Cart View

Before create cart view, need add to cart function.

# views.py

def add_to_cart(request, item_id):
    # Get or create a cart for the user
    cart, created = Cart.objects.get_or_create(user=request.user)

    # Get the item to be added to the cart
    item = get_object_or_404(Item, id=item_id)

    # Check if the item is already in the cart
    cart_item, created = CartItem.objects.get_or_create(
        item=item,
        cart=cart,
        defaults={'quantity': 1, 'price': item.price}
    )
    
    if not created:
        # If the item already exists in the cart, update the quantity
        cart_item.quantity += 1
        cart_item.save()

    return redirect('item-list')  # Redirect to wherever you want after adding to the cart
def cart_list(request):
    cart, created = Cart.objects.get_or_create(user=request.user)
    cart_items = CartItem.objects.filter(cart=cart)
    context = {
        "cart": cart,
        "cart_items": cart_items
    }
    return render(request, "ecommerce/cart.html", context)

des4

Forms

Review Form

First, create a review form class.

# forms.py

class ReviewForm(forms.ModelForm):

    class Meta:
        model = Review
        fields = '__all__'

# views.py

def create_review(request, item_id):
    item = Item.objects.get(id=item_id)
    review_form = ReviewForm()

    if request.method == 'POST':
        rate = request.POST.get('rate') 
        comment = request.POST.get('comment')  

        review = Review(
            item=item,
            user=request.user, 
            rate=rate,
            comment=comment
        )
        review.save()
        return redirect('item-detail', item_id=item_id)

    context = {
        'item': item,
        'form': review_form
    }
    return render(request, "forms/review_form.html", context)

I added this in item detail view and when clicked, redirect to create review form page.

<a href="{% url 'create-review' item.id %}">Create Review</a>

Order Form

I don’t need all of the fields, so

class OrderForm(forms.ModelForm):

    class Meta:
        model = Order
        fields = [
            'firstName', 
            'lastName', 
            'email', 
            'address', 
            'city',
            'province',
            'postalCode', 
        ]
        

and create the view. Before, cart_items should be sent to this view, so I added session in cart-list view function to send items. price should be casted to str since session is json format.

def cart_list(request):
    cart, created = Cart.objects.get_or_create(user=request.user)
    cart_items = CartItem.objects.filter(cart=cart)
    total_amount = sum(item.quantity * item.price for item in cart_items)

    cart_items_data = [
        {
            'item_id': item.item.id,
            'item_name': item.item.name,
            'quantity': item.quantity,
            'price': str(item.price) 
        }
        for item in cart_items
    ]
    request.session['cart_items'] = cart_items_data
    context = {
        "cart": cart,
        "cart_items": cart_items,
        "total": total_amount
    }
    return render(request, "ecommerce/cart.html", context)

and order form view.

def order_form(request):
    order_form = OrderForm()
    cart_items = request.session.get('cart_items')
    total_amount = sum(
        float(item['quantity']) * float(item['price'])
        for item in cart_items
    )

    if cart_items is None:
        return redirect('cart-list')

    if request.method == 'POST':
        firstName = request.POST.get('firstName')
        lastName = request.POST.get('lastName')
        email = request.POST.get('email')
        address = request.POST.get('address')
        city = request.POST.get('city')
        country = request.POST.get('country')
        province = request.POST.get('province')
        postalCode = request.POST.get('postalCode')

        order = Order(
            user=request.user, 
            firstName=firstName,
            lastName=lastName,
            email=email,
            address=address,
            city=city,
            country=country,
            province=province,
            postalCode=postalCode,
        )
        order.save()
        return redirect('item-list')

    context = {
        'form': order_form,
        'cart_items': cart_items,
        'total' :total_amount
    }

    return render(request, "forms/order_form.html", context)

des5

Learned New

‘login_required’ decorator in Django is used to ensure that a user is authenticated (logged in) before they can access a particular view. If the user is not logged in, they will be automatically redirected to the login page.

from django.contrib.auth.decorators import login_required

@login_required
def user_profile(request, user_id):
    ...

And add this in settings.py.

# settings.py
LOGIN_URL = '/login/'