Django Models in E-Commerce Website Development

假设我们有个电商网站,一个基本的流程就是用户下单,然后进入购物车cart, 然后进入checkout。 假设我们有如下比较简单的Data Structure:

简单的数据结构

1.针对这个数据结构来build data model:

models.py in the 'store' app

from django.db import models
from django.contrib.auth.models import User
# Create your models here.


class Customer(models.Model):
    user = models.OneToOneField(
        User, null=True, blank=True, on_delete=models.CASCADE)
    name = models.CharField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True)

    def __str__(self):
        return self.name


class Product(models.Model):
    name = models.CharField(max_length=200, null=True)
    price = models.FloatField()
    digital = models.BooleanField(default=False, null=True, blank=False)
    image = models.ImageField(null=True, blank=True)

    def __str__(self):
        return self.name

    @property
    def imageURL(self):
        try:
            url = self.image.url
        except:
            url = ""
        return url


class Order(models.Model):
    customer = models.ForeignKey(
        Customer, on_delete=models.SET_NULL, null=True, blank=True)
    date_ordered = models.DateTimeField(auto_now_add=True)
    complete = models.BooleanField(default=False, null=True, blank=False)
    transaction_id = models.CharField(max_length=200, null=True)

    def __str__(self):
        return str(self.id)

    @property
    def get_cart_total(self):
        orderitems = self.orderitem_set.all()
        total = sum([item.get_total for item in orderitems])
        return total

    @property
    def get_cart_items_quantity(self):
        orderitems = self.orderitem_set.all()
        total = sum([item.quantity for item in orderitems])
        return total


class OrderItem(models.Model):
    product = models.ForeignKey(
        Product, on_delete=models.SET_NULL, null=True, blank=True)
    order = models.ForeignKey(
        Order, on_delete=models.SET_NULL, null=True, blank=True)
    quantity = models.IntegerField(default=0, null=True, blank=True)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.product.name)

    @property
    def get_total(self):
        total = self.product.price * self.quantity
        return total


class ShippingAddress(models.Model):
    customer = models.ForeignKey(
        Customer, on_delete=models.SET_NULL, null=True, blank=True)
    order = models.ForeignKey(
        Order, on_delete=models.SET_NULL, null=True, blank=True)
    address = models.CharField(max_length=200, null=True)
    city = models.CharField(max_length=200, null=True)
    state = models.CharField(max_length=200, null=True)
    zipcode = models.CharField(max_length=200, null=True)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.address

注意下其中的image这个需要安装pillow

pipenv install pillow

2.model需要进行makingmigrations这样就会创建Customer, Order...这些不同的models

python manage.py makingmigrations 

然后进行migrate

python manage.py migrate

这样就算把Data Structure建立好了,如果DB有实际的数据的话,一个简单的访问数据的方式就是Order.objects.all()或者Product.objects.all()

3. 把这些model加到admin后台以准备手动添加数据:

admin.py

from django.contrib import admin


# Register your models here.
from .models import *

admin.site.register(Customer)
admin.site.register(Product)
admin.site.register(Order)
admin.site.register(OrderItem)
admin.site.register(ShippingAddress)

4. 创建超级用户来手动添加数据

python manage.py createsuperuser

127.0.0.1:8000/admin 就可以访问了

4.1 手动添加product, customer, order, orderitem等数据

4.2 为了给商品动态添加图片

采用在后台上传图片的方式而不是直接在项目的images文件中直接添加图片。 那么上传的图片你需要告诉项目存在项目的什么地方,所以需要在settings中添加:


MEDIA_URL = '/images/'

MEDIA_ROOT = os.path.join(BASE_DIR, "static/images")

然后再urls.py中添加:

from django.conf.urls.static import static
from django.conf import settings
....

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这样后台upload image到对应的product时候,系统会自动将图片添加到static/images下

5. 把添加的数据反映到网页上,需要修改views.py和对应xxx.html:

注意其中Order.objects.get_or_create(customer=customer, complete=False)的使用是根据目前还没有结账的该登录用户的信息query这个用户的order的中item有哪些,如果没有order就创建order.
items = order.orderitem_set.all() 表示用这个order去拿到所有order下的items,因为建立模型的时候就是一个order(parent)对应多个items(child with model 'OrderItem'), 所以这个方法其实是 parentmodel.lowercasesofchildmodel_set.all()

from django.shortcuts import render
from .models import *
# Create your views here.


def store(request):
    products = Product.objects.all()
    context = {"products": products}
    return render(request, 'store/store.html', context)


def cart(request):

    # user has logged in:
    if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(
            customer=customer, complete=False)
        items = order.orderitem_set.all()

    # user has not logged in:
    else:
        items = []
        order = {'get_cart_total': 0, 'get_cart_items_quantity': 0}

    context = {"items": items, "order_of_this_transaction": order}
    print("context:")
    print(context)
    return render(request, 'store/cart.html', context)


def checkout(request):

    if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(
            customer=customer, complete=False)
        items = order.orderitem_set.all()

    else:
        items = []
        order = {'get_cart_total': 0, 'get_cart_items_quantity': 0}

    context = {"items": items, "order_of_this_transaction": order}
    return render(request, 'store/checkout.html', context)

把这些拿到的值拿去render对应html文件的方式就是用
context = {a_key_belonging_to_some_model: value}
然后传入context, html文件取这些值的方式就是{{a_key_belonging_to_some_model.xxx}},比如item对应的model就是orderitem, 里面有成员quantity, 所以直接item.quantity就可以拿到这个物品的数量。orderitem有外键product, 而product这个model有成员name,所以item.product.name可以拿到这个item对应的product的name.

item.get_total的用法其实是在models.py里面用了python的property decorator, 关于为什么要用property decorator,这里有篇不错的文章做了解释.

比如下面就是在cart.html中的render出数据的一段代码:

{% for item in items %}
  
{{item.product.name}}
SEK {{item.product.price|floatformat:2}}

{{item.quantity}}

SEK {{ item.get_total }}
{% endfor %}

你可能感兴趣的:(Django Models in E-Commerce Website Development)