美文网首页
Django Models in E-Commerce Webs

Django Models in E-Commerce Webs

作者: realnickman | 来源:发表于2020-06-14 06:19 被阅读0次

    假设我们有个电商网站,一个基本的流程就是用户下单,然后进入购物车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 %}
      <div class="row cart-row align-items-center">
        <div class="col-lg-3">
          <img class="row-image" src="{{item.product.imageURL}}" alt="" />
        </div>
        <div class="col-lg-3 table-content">{{item.product.name}}</div>
        <div class="col-lg-2 table-content">
          SEK {{item.product.price|floatformat:2}}
        </div>
        <div class="col-lg-2 table-content quantity-container">
          <div class="quantity">
            <img
              src="{% static 'images/up-arrow.png' %}"
              alt=""
              class="chg-quantity"
            />
            <img
              src="{% static 'images/down-arrow.png' %}"
              alt=""
              class="chg-quantity"
            />
          </div>
          <p class="quantity">
            {{item.quantity}}
          </p>
        </div>
        <div class="col-lg-2 table-content">
          <span>SEK {{ item.get_total }}</span>
        </div>
      </div>
      {% endfor %}
    </div>
    

    相关文章

      网友评论

          本文标题:Django Models in E-Commerce Webs

          本文链接:https://www.haomeiwen.com/subject/nuwtxktx.html