每天生鮮-思路數據庫設計html
全文檢索python
每天生鮮-靜態文件mysql
daily_fresh_demo
- daily_fresh_demo
- df_cart # 購物車功能
- df_goods # 商品功能
- df_order # 訂單功能
- df_user # 用戶功能(包括登陸驗證等相關功能)
- static # 靜態文件
- templates # 前段模板-
whoosh_index # 全局索引文件
db.sqlite3
manage.py
注:這個電商網站是博主在接觸Django以後作的第一個項目,還有不少地方須要改進。若是有須要項目相關視頻資源的朋友能夠博客園私信,或者評論區留言,博主會在看到的第一時間分享。
附github源碼地址(包含靜態文件):https://github.com/weilanhanf/daily_fresh_demogit
daily_fresh_demo
- daily_fresh_demo
- settings.py
- urls.py
- wsgi.py
- __init__.py # 這裏使用Django自帶的小型sqlite數據庫,若是使用mysql就須要在這裏添加相應的驅動
1 import os 2 3 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 4 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 6 7 # Quick-start development settings - unsuitable for production 8 # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ 9 10 # SECURITY WARNING: keep the secret key used in production secret! 11 SECRET_KEY = 'uey!i4x26n!$d-73cs%blri)09#xfud_e361ne2h(#s27)l!' 12 13 # SECURITY WARNING: don't run with debug turned on in production! 14 DEBUG = True 15 16 ALLOWED_HOSTS = [] 17 18 19 # Application definition 20 21 INSTALLED_APPS = [ 22 'django.contrib.admin', 23 'django.contrib.auth', 24 'django.contrib.contenttypes', 25 'django.contrib.sessions', 26 'django.contrib.messages', 27 'django.contrib.staticfiles', 28 'df_user', 29 'df_goods', 30 'df_cart', 31 'df_order', 32 'tinymce',#使用富文本編輯框要在settings文件中安裝 33 'haystack',#全文檢索 34 ] 35 36 MIDDLEWARE = [ 37 'django.middleware.security.SecurityMiddleware', 38 'django.contrib.sessions.middleware.SessionMiddleware', 39 'django.middleware.common.CommonMiddleware', 40 'django.middleware.csrf.CsrfViewMiddleware', 41 'django.contrib.auth.middleware.AuthenticationMiddleware', 42 'django.contrib.messages.middleware.MessageMiddleware', 43 'django.middleware.clickjacking.XFrameOptionsMiddleware', 44 ] 45 46 ROOT_URLCONF = 'daily_fresh_demo.urls' 47 48 TEMPLATES = [ 49 { 50 'BACKEND': 'django.template.backends.django.DjangoTemplates', 51 'DIRS': [os.path.join(BASE_DIR, 'templates')] 52 , 53 'APP_DIRS': True, 54 'OPTIONS': { 55 'context_processors': [ 56 'django.template.context_processors.debug', 57 'django.template.context_processors.request', 58 'django.contrib.auth.context_processors.auth', 59 'django.contrib.messages.context_processors.messages', 60 ], 61 }, 62 }, 63 ] 64 65 WSGI_APPLICATION = 'daily_fresh_demo.wsgi.application' 66 67 68 # Database 69 # https://docs.djangoproject.com/en/2.0/ref/settings/#databases 70 71 DATABASES = { 72 'default': { 73 'ENGINE': 'django.db.backends.sqlite3', 74 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 75 }, 76 'OPTIONS':{ 77 'TIMEOUT': 20, 78 } 79 } 80 81 82 # Password validation 83 # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators 84 85 AUTH_PASSWORD_VALIDATORS = [ 86 { 87 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 88 }, 89 { 90 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 91 }, 92 { 93 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 94 }, 95 { 96 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 97 }, 98 ] 99 100 101 # Internationalization 102 # https://docs.djangoproject.com/en/2.0/topics/i18n/ 103 104 LANGUAGE_CODE = 'en-us' 105 106 TIME_ZONE = 'UTC' 107 108 USE_I18N = True 109 110 USE_L10N = True 111 112 USE_TZ = True 113 114 115 # Static files (CSS, JavaScript, Images) 116 # https://docs.djangoproject.com/en/2.0/howto/static-files/ 117 118 STATIC_URL = '/static/' 119 STATICFILES_DIRS = [ 120 os.path.join(BASE_DIR, 'static'), 121 ] 122 123 #開發階段上傳文件目錄 124 MEDIA_ROOT = os.path.join(BASE_DIR, 'static') 125 #部署後的上傳文件目錄 126 # MEDIA_ROOT = 'var/www/daily_fresh_demo/static' 127 128 129 #富文本編輯框的使用配置 130 TINYMCE_DEFAULT_CONFIG = { 131 'theme': 'advanced', 132 'width': 600, 133 'height': 400, 134 } 135 136 HAYSTACK_CONNECTIONS = { 137 'default':{ 138 #使用whoosh引擎 139 'ENGINE':'haystack.backends.whoosh_cn_backend.WhooshEngine', 140 #添加索引文件路徑 141 'PATH':os.path.join(BASE_DIR, 'whoosh_index'), 142 } 143 } 144 #當修改刪除數據時,自動生成索引 145 HAYSTACK_SIGNAL_PROCESSOR ='haystack.signals.RealtimeSignalProcessor' 146 # HAYSTACK_DEFAULT_OPERATOR = 'OR' 147 HAYSTACK_SEARCH_RESULTS_PER_PAGE = 18#每一頁顯示多少數據
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^', include('df_goods.urls',namespace='goods')),
url(r'^user/', include('df_user.urls', namespace='user')),
url(r'^goods/', include('df_goods.urls')),
url(r'^cart/',include('df_cart.urls', namespace='cart')),
url(r'^order/',include('df_order.urls', namespace='order')),
url(r'^search/', include('haystack.urls')),#全文檢索
url(r'^tinymce/', include('tinymce.urls')),#使用富文本編輯框配置confurl
]
app目錄以下github
df_user
- migrations # 遷移文件目錄
- admin.py
- apps.py
- models.py
- test.py
- urls.py
- user_docorator.py # 這裏使用裝飾器作用戶身份認證
- views.py
- __init__.py
from django.apps import AppConfig
class DfUserConfig(AppConfig):
name = 'df_user'
from django.db import models # Create your models here. class UserInfo(models.Model): uname=models.CharField(max_length=20) upwd=models.CharField(max_length=40) uemail=models.CharField(max_length=30) ushou=models.CharField(max_length=20,default="") uaddress=models.CharField(max_length=100,default="") uyoubian=models.CharField(max_length=6,default="") uphone=models.CharField(max_length=11,default="") # default,blank是python層面的約束,不影響數據庫表結構,修改時不須要遷移 python manage.py makemigrations class GoodsBrowser(models.Model): user=models.ForeignKey('UserInfo', on_delete=models.CASCADE) good=models.ForeignKey('df_goods.GoodsInfo', on_delete=models.CASCADE)
#!/user/bin/env python # -*- coding: utf-8 -*- from django.conf.urls import url from . import views app_name = 'df_user' urlpatterns = [ url(r'^register/$', views.register), url(r'^register_handle/$', views.register_handle), url(r'^register_exist/$', views.register_exist), url(r'^login/$', views.login), url(r'^login_handle/$', views.login_handle), url(r'^info/$', views.info), url(r'^order/(\d+)$', views.order), url(r'^site/$', views.site), # url(r'^place_order/$', views.place_order), url(r'^logout/$', views.logout) ]
from django.shortcuts import render, redirect, HttpResponseRedirect, HttpResponse from django.http import JsonResponse from .models import UserInfo from df_goods.models import GoodsInfo from df_user.models import GoodsBrowser from df_order.models import * from hashlib import sha1 from . import user_decorator from django.core.paginator import Paginator,Page def register(request): context={ 'title':'用戶註冊', } return render(request, 'df_user/register.html', context) def register_handle(request): #接受用戶輸入 post = request.POST print(request.method) uname=post.get('user_name') upwd=post.get('pwd') upwd2=post.get('cpwd') uemail=post.get('email') #判斷兩次密碼一致性 if upwd != upwd2: return redirect('/user/register/') #密碼加密 s1=sha1() s1.update(upwd.encode('utf8')) upwd3=s1.hexdigest() # sha = hashlib.sha1(upwd.encode('utf8')) # sha.hexdigest() #建立對象 user=UserInfo() user.uname=uname user.upwd=upwd3 user.uemail=uemail user.save() print(uname, upwd3,uemail) #註冊成功 context = { 'title': '用戶登錄', 'uname': uname, } # return redirect('/user/login/') return render(request, 'df_user/login.html', context) def register_exist(request): uname=request.GET.get('uname') count=UserInfo.objects.filter(uname=uname).count() if count == 0: print('當前用戶名可用') return JsonResponse({'count':count}) # @user_decorator.request_detail def login(request): print(request.get_full_path(), 'request.get_full_path') uname=request.COOKIES.get('uname', '') context={ 'title': '用戶登錄', 'error_name':0, 'error_pwd':0, 'uname':uname, } return render(request, 'df_user/login.html', context) def login_handle(request):#沒有利用ajax提交表單 #接受請求信息 post = request.POST uname = post.get('username') upwd = post.get('pwd') jizhu = post.get('jizhu', 0) #根據用戶名查詢對象 # print(uname, upwd, jizhu, request.method) users = UserInfo.objects.filter(uname=uname)#[] print(uname,len(users), users) #判斷若是未查到則用戶名錯誤,若是查到則判斷密碼是否正確,正確則轉到用戶中心 if len(users)==1: s1 = sha1() s1.update(upwd.encode('utf8')) if s1.hexdigest()==users[0].upwd: print("驗證成功") # request.COOKIES['url'] = '/8/' url = request.COOKIES.get('url','/') print(url) red = HttpResponseRedirect(url)#繼承與HttpResponse 在跳轉的同時 設置一個cookie值 #是否勾選記住用戶名,設置cookie if jizhu!=0: red.set_cookie('uname', uname) # print('設置cookie', request.COOKIES['uname']) else: red.set_cookie('uname', '',max_age=-1)#設置過時cookie時間,馬上過時 request.session['user_id'] = users[0].id request.session['user_name'] = uname return red else: context = { 'title':'用戶名登錄', 'error_name': 0, 'error_pwd':1, 'uname':uname, 'upwd':upwd, } # print('密碼錯誤') return render(request, 'df_user/login.html', context) else: context = { 'title': '用戶名登錄', 'error_name': 1, 'error_pwd': 0, 'uname': uname, 'upwd': upwd, } print('不存在當前用戶') return render(request, 'df_user/login.html', context) def logout(request): request.session.flush()#清空當前用戶全部session return redirect('/') @user_decorator.login def info(request): username =request.session.get('user_name') # print(username) user = UserInfo.objects.filter(uname = username).first() # user = UserInfo.objects.get(id=request.session['user_id']) # print(request.session['user_name']) #列表形式最近瀏覽 # goods_ids = request.COOKIES.get('goods_ids', '') # print('cookies', goods_ids) #在cookie中goods_id以{ 'gooids':'1,5,6,7,8,9'}形式存入 # goods_ids1 = goods_ids.split(',')#拆分爲列表 # print('最近瀏覽商品序號',goods_ids1) # goods_list1 = GoodsInfo.objects.filter(id__in=goods_ids1)#會破壞瀏覽商品的前後順序 # if goods_ids1[0] != '' : # goods_list = [GoodsInfo.objects.get(id=int(goods_id)) for goods_id in goods_ids1] # # for goods_id in goods_ids1: # # goods_list.append(GoodsInfo.objects.get(id=int(goods_id)))#pk與id區別 # # 每次只查詢一個商品並放入列表的最後,保證了瀏覽商品的順序 # explain = '最近瀏覽' # else: # goods_list = [] # explain = '無最近瀏覽' # 最近瀏覽計入第三張那個表 goods_ids = GoodsBrowser.objects.filter(user_id=request.session['user_id']) # print(goods_ids) goods_ids1 = [good_browser.good_id for good_browser in goods_ids] # print(goods_ids1) # goods_ids2 = [] # for good_id in goods_ids1: # if good_id not in goods_ids2: # goods_ids2.append(good_id) # print(goods_ids2) if len(goods_ids1) != 0: goods_list = [GoodsInfo.objects.get(id=goods_id) for goods_id in goods_ids1] goods_list.reverse() # print(goods_list) explain = '最近瀏覽' else: goods_list = [] explain = '無最近瀏覽' context={ 'title':'用戶中心', 'page_name': 1, 'user_phone':user.uphone, 'user_address':user.uaddress, 'user_name':request.session['user_name'], 'goods_list': goods_list, 'explain': explain, } # print(user.uname, user.uaddress, user.uphone) return render(request, 'df_user/user_center_info.html', context) @user_decorator.login def order(request, index): user_id = request.session['user_id'] orders_list = OrderInfo.objects.filter(user_id=int(user_id)).order_by('-odate') # print(len(orders_list)) # print(orders_list) paginator = Paginator(orders_list,2) page = paginator.page(int(index)) context={ 'paginator': paginator, 'page':page, # 'orders_list':orders_list, 'title':"用戶中心", 'page_name':1, } return render(request, 'df_user/user_center_order.html', context) @user_decorator.login def site(request): user = UserInfo.objects.get(id=request.session['user_id']) # print(user, type(user), user.uphone,user.uaddress) if request.method=="POST": post = request.POST user.ushou = post.get('ushou') user.uaddress = post.get('uaddress') user.uyoubian = post.get('uyoubian') user.uphone = post.get('uphone') user.save() context = { 'page_name': 1, 'title': '用戶中心', 'user':user, } return render(request, 'df_user/user_center_site.html', context)
對用戶進行身份認證,如用戶進入我的中心的時候須要驗證,購買商品也須要身份驗證ajax
#!/user/bin/env python # -*- coding: utf-8 -*- from django.http import HttpResponseRedirect import re #若是未登陸則轉到登錄頁面 def login(func): def login_fun(request, *args, **kwargs): if 'user_id' in request.session: return func(request, *args, **kwargs) else: red = HttpResponseRedirect('/user/login/') red.set_cookie('url', request.get_full_path()) print(request.get_full_path(), 'user_decorator') #保證用戶再登錄驗證以後仍點擊到但願的頁面 return red return login_fun """ http://127.0.0.1:8000/200/?type=10 request.path :表示當前路徑,爲/200/ request.get_full_path():表示完整路徑,爲/200/?type=10 """
app目錄以下sql
df_goods - migrations - admin.py - apps.py - models.py - search_indexes.py # 搜索商品功能 - tests.py - urls.py - views.py - __init__.py
from django.apps import AppConfig class DfGoodsConfig(AppConfig): name = 'df_goods'
from django.db import models from tinymce.models import HTMLField#使用富文本編輯框要在settings文件中安裝 #將一對多的關係維護在GoodsInfo中維護,另外商品信息與分類信息都屬於重要信息須要使用邏輯刪除 # Create your models here. class TypeInfo(models.Model):#商品分類信息 水果 海鮮等 isDelete = models.BooleanField(default=False)#邏輯刪除 ttitle = models.CharField(max_length=20) def __str__(self):#這裏定義在admin中要顯示的內容 # return self.ttitle.encode('utf-8') return self.ttitle class GoodsInfo(models.Model):#具體商品信息 isDelete = models.BooleanField(default=False)#邏輯刪除 gtitle = models.CharField(max_length=20)#商品的名稱 gpic = models.ImageField(upload_to='df_goods')#關聯圖片目錄 gprice = models.DecimalField(max_digits=5, decimal_places=2)#商品價格小數位爲兩位,整數位爲3位 gunit = models.CharField(max_length=20, default='500g')#商品單位kg或者個數 gclick = models.IntegerField()#商品點擊量 gjianjie = models.CharField(max_length=200)#商品簡介 gkucun = models.IntegerField()#商品庫存 gcontent = HTMLField()#商品介紹 gtype = models.ForeignKey(TypeInfo, on_delete=models.CASCADE)#外鍵關聯TypeInfo表 # gadv = models.BooleanField(default=False)#商品是否推薦 def __str__(self): # return self.gtitle.encode('utf-8') return self.gtitle # python3中 __str__ 不能接收bytes類型的數據,這和python2/3的編解碼方式是有關係的。
#!/user/bin/env python # -*- coding: utf-8 -*- from django.conf.urls import url from . import views from .views import * app_name = 'df_goods' urlpatterns = [ url('^$', views.index), url('^list(\d+)_(\d+)_(\d+)/$', views.list), url('^(\d+)/$', views.detail), url(r'^search/', MySearchView()),#全文檢索 url(r'^cookieTest/', views.cookieTest) ]
from django.shortcuts import render, HttpResponse from .models import * from django.core.paginator import Page, Paginator from df_cart.models import CartInfo from df_user.models import GoodsBrowser from haystack.views import SearchView # Create your views here. def index(request): #查詢各個分類的最新4條,最熱4條數據 typelist = TypeInfo.objects.all() print(len(typelist), 'asdf') # 連表操做(了不得的雙下劃線)利用雙下劃線和 _set將表之間的操做鏈接起來 type0 = typelist[0].goodsinfo_set.order_by('-id')[0:4]#按照最新上傳的水果顯示 type01 = typelist[0].goodsinfo_set.order_by('-gclick')[0:4]#按照用戶點擊量上傳 type1 = typelist[1].goodsinfo_set.order_by('-id')[0:4] type11 = typelist[1].goodsinfo_set.order_by('-gclick')[0:4] type2 = typelist[2].goodsinfo_set.order_by('-id')[0:4] type21 = typelist[2].goodsinfo_set.order_by('-gclick')[0:4] type3 = typelist[3].goodsinfo_set.order_by('-id')[0:4] type31 = typelist[3].goodsinfo_set.order_by('-gclick')[0:4] type4 = typelist[4].goodsinfo_set.order_by('-id')[0:4] type41 = typelist[4].goodsinfo_set.order_by('-gclick')[0:4] type5 = typelist[5].goodsinfo_set.order_by('-id')[0:4] type51 = typelist[5].goodsinfo_set.order_by('-gclick')[0:4] #判斷是否存在登陸狀態 try: user_id = request.session['user_id'] cart_count = CartInfo.objects.filter(user_id=int(user_id)).count except: cart_count = 0 context = { 'title': '首頁', 'cart_count': cart_count, 'guest_cart':1, 'type0':type0, 'type01':type01, 'type1':type1, 'type11':type11, 'type2':type2, 'type21':type21, 'type3':type3, 'type31':type31, 'type4':type4, 'type41':type41, 'type5':type5, 'type51':type51, } """ context = { 'guest_cart':1, 'title': '首頁' } #獲取最新的4個商品 hot = GoodsInfo.objects.all().order_by('-gclick')[0:4] context.setdefault('hot', hot) #*******獲取各分類下的點擊商品******* #首先獲取分類 typelist = TypeInfo.objects.all() for i in range(len(typelist)): #獲取type對象 type = typelist[i] #根據type對象獲取商品列表 #經過外鍵關聯獲取商品 #獲取對應列表中的經過id倒序排列的前四個 goods1 = type.goodinfo_set.order_by('-id')[0:4] goods2 = type.goodinfo_set.order_by('-gclick')[0:4] key1 = 'type' + str(i) # 根據id 倒敘排列 key2 = 'type' + str(i) + str(i) # 根據點擊量倒序排列 context.setdefault(key1, goods1) context.setdefault(key2, goods2) print(context) """ # print(type0, type01) # for i in type0: # print(i.gpic) return render(request, 'df_goods/index.html', context) def list(request, tid, pindex, sort): #tid:商品種類信息 pindex:商品頁碼 sort:商品顯示分類方式 typeinfo = TypeInfo.objects.get(pk=int(tid)) #根據主鍵查找當前的商品分類 海鮮或者水果 news = typeinfo.goodsinfo_set.order_by('-id')[0:2] #list.html左側最新商品推薦 goods_list = [] # list中間欄商品顯示方式 if sort == '1':#默認最新 goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-id') elif sort == '2':#按照價格 goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gprice') elif sort == '3':#按照人氣點擊量 goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gclick') #建立Paginator一個分頁對象 paginator = Paginator(goods_list, 4) #返回Page對象,包含商品信息 page = paginator.page(int(pindex)) context = { 'title': '商品列表', 'guest_cart': 1, 'page': page, 'paginator': paginator, 'typeinfo': typeinfo, 'sort': sort, # 排序方式 'news': news, } return render(request,'df_goods/list.html',context) def detail(request, id): goods = GoodsInfo.objects.get(pk=int(id)) goods.gclick = goods.gclick+1#商品點擊量 goods.save() news = goods.gtype.goodsinfo_set.order_by('-id')[0:2] context = { 'title': goods.gtype.ttitle, 'guest_cart': 1, 'goods': goods, 'news': news, 'id':id, } response=render(request, 'df_goods/detail.html', context) #使用列表 記錄最近瀏覽, 在用戶中心使用 # goods_ids = request.COOKIES.get('goods_ids', '')#在cookie中創建一個商品id的對應最近瀏覽的商品 # goods_id = '%d' %goods.id#將url轉化爲整型 # if goods_ids != '':#判斷是否存在瀏覽記錄,若是存在則繼續判斷, # goods_ids1 = goods_ids.split(',')#拆分爲列表 # if goods_ids1.count(goods_id)>=1:#若是商品已經存在記錄則刪除舊紀錄 # goods_ids1.remove(goods_id) # goods_ids1.insert(0, goods_id)#將商品插入到第一頁 # if len(goods_ids1)>=6:#每頁只顯示五個最近瀏覽的商品 # del goods_ids1[5] # goods_ids = ','.join(goods_ids1)#將商品id拼接爲字符串 # else: # goods_ids = goods_id#顯然第一次查看detail頁面時爲空,則直接添加 # response.set_cookie('goods_ids', goods_ids)#寫入cookie # 將用戶最近瀏覽商品記錄進第三張表 ''' 1,判斷是否有用戶登陸, 若是沒有直接結束 2,判斷在當前瀏覽表中是否存在這個用戶, 不存在則建立一個用戶瀏覽記錄,而且不用判斷是否瀏覽過 若存在則判斷當前用戶是否存在一個瀏覽過當前商品 3,無論有沒有瀏覽過當前商品都要先建立一個商品記錄放入表中 若是瀏覽過則刪除前期瀏覽的商品 若沒有則不用刪除 4,若是商品記錄爲五條,則將最後的一條刪除 ''' try: user_id = request.session['user_id'] # user_list = GoodsBrowser.objects.filter(user_id=int(user_id)) goods_browser = GoodsBrowser() goods_browser.user_id = int(user_id) goods_browser.good_id = int(id) goods_browser.save() old_user_list = GoodsBrowser.objects.filter(user_id=int(user_id), good_id=int(id)) if len(old_user_list) > 1: GoodsBrowser.objects.filter(good_id=int(id)).first().delete() if len(GoodsBrowser.objects.filter(user_id=int(user_id))) > 5: GoodsBrowser.objects.filter(user_id=int(user_id)).first().delete() except: pass return response def cart_count(request): if request.session.has_key('user_id'): return CartInfo.objects.filter(user_id=request.session['user_id']).count else: return 0 class MySearchView(SearchView): def extra_context(self): context = super(MySearchView, self).extra_context() context['title'] = '搜索' context['guest_cart'] = 1 context['cart_count'] = cart_count(self.request) return context def cookieTest(request): response = HttpResponse() if request.COOKIES.get('binggan'):#判斷是否有此cookie cookie = request.COOKIES response.write(cookie['binggan'])#若是有則寫入 return response
from django.contrib import admin from .models import TypeInfo,GoodsInfo # Register your models here. #註冊模型類 普通方法 class TypeInfoAdmin(admin.ModelAdmin): list_display = ['id', 'ttitle'] # class GoodsInfoAdmin(admin.ModelAdmin): # list_per_page = 15 # list_display = ['id', 'gtitle', 'gunit','gclick', 'gprice','gpic','gjianjie','gkucun','gcontent','gjianjie'] admin.site.register(TypeInfo, TypeInfoAdmin) # admin.site.register(GoodsInfo, GoodsInfoAdmin) # 裝飾器方法 @admin.register(GoodsInfo) class GoodsInfoAdmin(admin.ModelAdmin): list_per_page = 15 list_display = ['id', 'gtitle', 'gunit','gclick', 'gprice','gpic','gjianjie','gkucun','gcontent','gjianjie']
#!/user/bin/env python # -*- coding: utf-8 -*- from haystack import indexes from .models import * #制定對於某個類的某些數據創建索引 class GoodsInfoIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) def get_model(self):#對GoodsInfo模型類進行索引 return GoodsInfo def index_queryset(self, using=None): return self.get_model().objects.all()
全局索引提供一個大的全局搜索功能,也能夠經過Django 中的ORM的Q查詢實現
這裏請參考全局索引:https://www.cnblogs.com/welan/p/9231430.html數據庫
app目錄以下django
df_order - migrations - admin.py - apps.py - models.py - tests.py - urls.py - views.py - __init__.py
from django.apps import AppConfig class DfOrderConfig(AppConfig): name = 'df_order'
from django.db import models # Create your models here. class OrderInfo(models.Model):#大訂單 oid = models.CharField(max_length=20, primary_key=True)#訂單號 user = models.ForeignKey('df_user.UserInfo', on_delete=models.CASCADE)#肯定哪一個用戶的訂單 odate = models.DateTimeField(auto_now=True) oIsPay = models.BooleanField(default=False)#當前訂單是否支付,默認爲否 ototal = models.DecimalField(max_digits=8, decimal_places=2) oaddress = models.CharField(max_length=150) #雖然訂單總價能夠由多個商品的單價以及數量求得,可是因爲用戶訂單的總價的大量使用,忽略total的冗餘度 #沒法實現:真實支付,物流信息 class OrderDetailInfo(models.Model):#大訂單中的具體某一商品訂單 goods = models.ForeignKey('df_goods.GoodsInfo',on_delete=models.CASCADE)#關聯商品信息 order = models.ForeignKey('OrderInfo', on_delete=models.CASCADE)#關聯大訂單,肯定屬於某一個大訂單中 price = models.DecimalField(max_digits=6, decimal_places=2)#某一類商品訂單的價格最高達9999.99 count = models.IntegerField()
#!/user/bin/env python # -*- coding: utf-8 -*- from django.conf.urls import url from . import views app_name = 'df_order' urlpatterns = [ url(r'^$', views.order), url(r'^push/$', views.order_handle), ]
from django.shortcuts import render,HttpResponse,redirect from df_user import user_decorator from django.db import transaction from django.http import JsonResponse from datetime import datetime from decimal import Decimal from .models import * from df_cart.models import CartInfo from df_user.models import UserInfo # Create your views here. @user_decorator.login def order(request): uid = request.session['user_id'] user = UserInfo.objects.get(id=uid) cart_ids = request.GET.getlist('cart_id') carts = [] total_price = 0 for goods_id in cart_ids: cart = CartInfo.objects.get(id = goods_id) carts.append(cart) total_price = total_price + float(cart.count) * float(cart.goods.gprice) total_price = float('%0.2f'%total_price) trans_cost = 10#運費 total_trans_price = trans_cost + total_price # print(total_trans_price) # import datetime訂單提交時間 # value = datetime.datetime.now() # print(value) context = { 'title': '提交訂單', 'page_name': 1, 'user':user, 'carts': carts, 'total_price':float('%0.2f'%total_price), 'trans_cost': trans_cost, 'total_trans_price': total_trans_price, # 'value':value } return render(request, 'df_order/place_order.html', context) ''' 事務提交: 這些步驟中,任何一環節一旦出錯則所有退回1 1. 建立訂單對象 2. 判斷商品庫存是否充足 3. 建立 訂單 詳情 ,多個 4,修改商品庫存 5. 刪除購物車 ''' @user_decorator.login @transaction.atomic()#事務 def order_handle(request): tran_id = transaction.savepoint()#保存事務發生點 cart_ids = request.POST.get('cart_ids')#用戶提交的訂單購物車,此時cart_ids爲字符串,例如'1,2,3,' # print('訂單購物車', cart_ids) user_id = request.session['user_id']#獲取當前用戶的id # print('當前用戶', user_id) try: order_info = OrderInfo()#建立一個訂單對象 now = datetime.now() order_info.oid = '%s%d'%(now.strftime('%Y%m%d%H%M%S'), user_id)#訂單號爲訂單提交時間和用戶id的拼接 order_info.odate = now#訂單時間 # print('訂單時間', now) order_info.user_id = int(user_id)#訂單的用戶id order_info.ototal = Decimal(request.POST.get('total'))#從前端獲取的訂單總價 # print('總價', order_info.ototal) order_info.save()#保存訂單 for cart_id in cart_ids.split(','):#逐個對用戶提交訂單中的每類商品即每個小購物車 cart = CartInfo.objects.get(pk = cart_id)#從CartInfo表中獲取小購物車對象 order_detail = OrderDetailInfo()#大訂單中的每個小商品訂單 order_detail.order = order_info#外鍵關聯,小訂單與大訂單綁定 goods = cart.goods#具體商品 if cart.count <= goods.gkucun:#判斷庫存是否知足訂單,若是知足,修改數據庫 goods.gkucun = goods.gkucun - cart.count goods.save() # print(goods.gtitle,'庫存', goods.gkucun) order_detail.goods = goods order_detail.price = goods.gprice # print('小訂單價格',order_detail.price) order_detail.count = cart.count # print('小訂單商品數量', order_detail.count) order_detail.save() cart.delete()#並刪除當前購物車 else:#不然,則事務回滾,訂單取消 transaction.savepoint_rollback(tran_id) return HttpResponse('庫存不足') # return redirect('/cart/') data = { 'ok': 1, } transaction.savepoint_commit(tran_id) except Exception as e: print("%s"%e) print('未完成訂單提交') transaction.savepoint_rollback(tran_id)#事務任何一個環節出錯,則事務所有取消 # return HttpResponse('訂單提交成功') return JsonResponse(data) @user_decorator.login def pay(request): pass
app目錄以下
df_cart - migrations - admin.py - apps.py - models.py - test.py - urls.py - views.py - __init__.py
from django.apps import AppConfig class DfCartConfig(AppConfig): name = 'df_cart'
from django.db import models # Create your models here. #當一對多關係時例如生鮮分類對生鮮具體商品, 將關係維護在多的那張表中,即在具體商品表中維護 #當多對多關係,則新建一張表,在再第三張表中維護表關係 #用戶表與商品表則將關係維護在購物車表中 #在購物車的邏輯刪除與物理刪除 選擇物理刪除, #購物車中的商品不屬於重要的信息,能夠直接刪除 class CartInfo(models.Model): user = models.ForeignKey('df_user.UserInfo', on_delete=models.CASCADE) goods = models.ForeignKey('df_goods.GoodsInfo', on_delete=models.CASCADE) #在同級工程目錄下引用外鍵 count = models.IntegerField()#記錄用戶買個多少單位的商品
#!/user/bin/env python # -*- coding: utf-8 -*- from django.conf.urls import url from . import views app_name = 'df_cart' urlpatterns = [ url(r'^$', views.cart), url(r'^add(\d+)_(\d+)/$', views.add), url(r'^edit(\d+)_(\d+)/$', views.edit), url(r'^delete(\d+)/$', views.delete), ]
from django.shortcuts import render,redirect from django.http import JsonResponse from df_user import user_decorator from .models import * # Create your views here. @user_decorator.login def cart(request): uid = request.session['user_id'] carts = CartInfo.objects.filter(user_id=uid) context = { 'title':'購物車', 'page_name':1, 'carts':carts } if request.is_ajax(): count = CartInfo.objects.filter(user_id=request.session['user_id']).count() #求當前用戶購買了幾件商品 return JsonResponse({'count': count}) else: return render(request, 'df_cart/cart.html', context) @user_decorator.login def add(request, gid, count): uid = request.session['user_id'] gid = int(gid) count = int(count) print(gid, count) #查詢購物車中是否已經有此商品,若是有則數量增長,若是沒有則新增 carts = CartInfo.objects.filter(user_id=uid, goods_id=gid) if len(carts)>=1: cart = carts[0] cart.count = cart.count + count else: cart = CartInfo() cart.user_id = uid cart.goods_id = gid cart.count = count cart.save() #若是是ajax提交則直接返回json,不然轉向購物車 if request.is_ajax(): count = CartInfo.objects.filter(user_id=request.session['user_id']).count() #求當前用戶購買了幾件商品 return JsonResponse({'count': count}) else: return redirect('/cart/') @user_decorator.login def edit(request, cart_id, count): try: cart = CartInfo.objects.get(pk=int(cart_id)) cart.count=int(count) cart.save() data = {'count':0} except Exception as e: data = {'count':count} return JsonResponse(data) @user_decorator.login def delete(request,cart_id): print(cart_id) try: cart = CartInfo.objects.get(pk=int(cart_id)) cart.delete() data={'ok':1} print('數據庫修改爲功') except Exception as e: data = {'ok':0} return JsonResponse(data)