項目演示:
Django實現簡易淘寶網站
一、安裝Django
在之前的博客中有相關文章,介紹了Django項目的搭建,今天在這裏來給大家分享一下,之前課程設計做的一個由Django實現的簡單淘寶網站。
Django的入門開發教程——搭建第一個項目(Windows系統)
二、目錄介紹
taobao/
├── manage.py # 管理文件
└── taobao # 項目目錄
├── __init__.py
├── settings.py # 配置
├── urls.py # 路由 --> URL和函數的對應關係
└── wsgi.py # runserver命令就使用wsgiref模塊做簡單的web server
三、運行Django項目
先cd taobao
切換進入Django項目路徑,然後執行以下命令:
python manage.py runserver
四、Setting配置文件
- 模板文件配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR + '/templates/'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- 靜態文件配置
STATIC_URL = '/templates/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "templates"),
]
五、創建的App
一個Django項目可以分爲很多個APP,用來隔離不同功能模塊的代碼。
在控制檯切換路徑到當前Django項目下,直接使用以下命令創建:
python manage.py startapp cart
:創建購物車
python manage.py startapp items
:創建商品類目
python manage.py startapp pay
:創建支付
python manage.py startapp user
:創建用戶
創建App的應用如下:
創建出來的app還需要到setting.py註冊才能用
INSTALLED_APPS = [
'django.contrib.admin',#這是一個管理站點,管理後臺應用
'django.contrib.auth',#這是一個權限框架。
'django.contrib.contenttypes',#這是一個內容類型的框架
'django.contrib.sessions',#這是一個會話(session)框架。
'django.contrib.messages',#這是一個消息框架。
'django.contrib.staticfiles',#這是一個用來管理靜態文件的框架
'items.apps.ItemsConfig',
'user.apps.UsersConfig',
]
重定向:
六、簡單淘寶網的前端
1. 購物車
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="/templates/style.css">
<title>王菜鳥的淘寶網--我的購物車</title>
</head>
<body class='relative cart-list'>
{% if list %}
<div class='item-list'>
{% for l in list %}
<div class='item-container'>
<img class='items' src={{l.image}} />
<div class="inline-block item-desc">
{{ l.price }}
{% if l.postal %}
包郵
{% endif %}
{{ l.title | safe}}
{{ l.shopNick }}
{{ l.payNum }}
</div>
<div class='option'>
<div class='count inline-block'>
數量 {{l.count}}
</div>
</div>
</div>
{% endfor %}
<form action="{%url 'pay:success' %}" method="POST">
{% csrf_token %}
<button class="to-pay">去結算</button>
</form>
</div>
{% else %}
<p>親,您的購物車是空的呢!請去添加商品到購物車吧~</p>
<a href="{%url 'items:index' %}">點擊此處返回首頁</a>
{% endif %}
</body>
</html>
2. 商品頁
<html lang="en">
<head>
<meta charset="utf -8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>王菜鳥的淘寶網</title>
<style>
form {
display: inline;
}
.add-to-cart {
color: #fff;
border-color: #f40;
background: #f40;
cursor: pointer;
width: 100px;
height: 22px;
text-align: center;
font-family: 'Hiragino Sans GB', 'microsoft yahei', sans-serif;
font-size: 10px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.to-pay {
position: absolute;
bottom: 10px;
right: 50%;
color: #fff;
border-color: #f40;
background: #f40;
cursor: pointer;
width: 100px;
height: 35px;
text-align: center;
font-family: 'Hiragino Sans GB', 'microsoft yahei', sans-serif;
font-size: 20px;
line-height: 35px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.relative {
position: relative;
}
.hidden {
display: none;
}
.inline-block {
display: inline-block;
}
.item-list .item-container {
vertical-align: top;
display: inline-block;
width: 18%;
border: 1px solid #eee;
background: #fff;
padding: 5px;
height: 335px;
position: relative;
margin-bottom: 15px;
}
.item-list .item-desc {
width: 100%;
font-size: 15px;
text-align: justify;
}
.item-list .items {
height: 240px;
width: 100%;
}
.item-list .option {
position: absolute;
bottom: 2px;
}
.cart-list {
padding-bottom: 80px;
}
.nav {
margin-bottom: 10px;
}
.nav .go-to-cart {
display: block;
color: #fff;
border-color: #f40;
background: #f40;
cursor: pointer;
width: 60px;
height: 22px;
line-height: 22px;
text-align: center;
font-family: 'Hiragino Sans GB', 'microsoft yahei', sans-serif;
font-size: 10px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
</style>
</head>
{% load static %}
<body>
<div class="nav">
<img src="{% static "banner.jpg" %}">
<h3 style="text-align:center;">親,歡迎您來到天貓購物喲,快來看看有沒有喜歡的加入購物車吧。</h3>
</div>
<div class="nav">
{% if request.sessions.user %}
歡迎你{{ request.session.user }}
{% else %}
<a href="{%url 'user:register'%}">註冊</a>
<a href="{%url 'user:login'%}">登錄</a>
<a href="https://www.taobao.com/" target="_blank">點擊此處訪問淘寶官網!</a>
{% endif %}
<a class="go-to-cart" href="{%url 'cart:list'%}">去購物車</a>
</div>
{% if list %}
<div class="item-list">
{% for l in list %}
<div class="item-container">
<img class="items" src="{{l.image}}" />
<div class="inline-block item-desc">
{{ l.price }} {% if l.postal %} 包郵 {% endif %} {{ l.title | safe}}
{{ l.shopNick }} {{ l.payNum }}
</div>
<div class="option">
<div class="count inline-block">
庫存 {{l.count}}
</div>
<form action="{%url 'cart:add-to-cart' l.id%}" method="POST">
{% csrf_token %}
<input class="hidden" />
<button
class="add-to-cart"
onclick="window.alert('添加成功')"
type="submit"
>
加入購物車
</button>
</form>
</div>
</div>
{% endfor %}
</div>
{% else %}
<p>親,您的購物車是空的呢!請去添加商品到購物車吧~</p>
{% endif %}
<h3 style="text-align:center;">技術支持:王菜鳥</h3>
<h5 style="text-align:center;">Powered by The king of rookies!</h5>
<h6 style="text-align:center;">[email protected]</h6>
</body>
</html>
3. 支付頁面
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>購物車結算</title>
</head>
<body>
<div>
支付成功!親,歡迎下次光臨呢~
<a href="{%url 'items:index' %}">點擊此處返回首頁</a>
</div>
</body>
</html>
form {
display: inline;
}
.add-to-cart {
color: #FFF;
border-color: #F40;
background: #F40;
cursor: pointer;
width: 100px;
height: 22px;
text-align: center;
font-family: "Hiragino Sans GB", "microsoft yahei", sans-serif;
font-size: 10px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.to-pay {
position: absolute;
bottom: 10px;
right: 50%;;
color: #FFF;
border-color: #F40;
background: #F40;
cursor: pointer;
width: 100px;
height: 35px;
text-align: center;
font-family: "Hiragino Sans GB", "microsoft yahei", sans-serif;
font-size: 20px;
line-height: 35px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.relative {
position: relative;
}
.hidden {
display: none
}
.inline-block {
display: inline-block;
}
.item-list .item-container {
vertical-align: top;
display: inline-block;
width: 18%;
border: 1px solid #eee;
background: #fff;
padding: 5px;
height: 335px;
position: relative;
margin-bottom: 15px;
}
.item-list .item-desc {
width: 100%;
font-size: 15px;
text-align: justify;
}
.item-list .items {
width: 100%;
}
.item-list .option {
position: absolute;
bottom: 2px;
}
.cart-list {
padding-bottom: 80px;
}
.nav {
margin-bottom: 10px;
}
.nav .go-to-cart {
display: inline-block;
color: #FFF;
border-color: #F40;
background: #F40;
cursor: pointer;
width: 60px;
height: 22px;
line-height: 22px;
text-align: center;
font-family: "Hiragino Sans GB", "microsoft yahei", sans-serif;
font-size: 10px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.nav .go-to-login {
display: inline-block;
margin-left: 5px;
color: #FFF;
border-color: #F40;
background: #F40;
cursor: pointer;
width: 60px;
height: 22px;
line-height: 22px;
text-align: center;
font-family: "Hiragino Sans GB", "microsoft yahei", sans-serif;
font-size: 10px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
5. 用戶註冊
<!DOCTYPE html>
<html>
<head>
<title>註冊</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<style type="text/css">
body{
background: #353f42;
{% comment %}
background-image: url(https://imgchr.com/content/images/system/home_cover_1552414407320_3a5f92.jpg);
background-repeat: no-repeat;
/* 當內容高度大於圖片高度時,背景圖像的位置相對於viewport固定 */
background-attachment: fixed; /*此條屬性必須設置否則可能無效*/
/* 讓背景圖基於容器大小伸縮 */
background-size: cover;
/* 設置背景顏色,背景圖加載過程中會顯示背景色 */
background-color: #CCCCCC; {% endcomment %}
}
#user_reg{
font-family: 微軟雅黑;
font-size: 40px;
text-align: center;
margin-top: 200px;
}
form{
width: 500px; /*設置寬度,方便使其居中*/
margin: 40px auto auto auto; /*上右下左*/
font-size: 25px;
}
input{
height: 30px;
width: 12em;
margin-top: 5px;
margin-bottom: 5px;
}
/*input標籤下的屬性選擇器*/
input[type="submit"],input[type="reset"]{
height: 25px;
width: 5em;
margin-top: 5px;
margin-left: 6px;
}
</style>
</head>
<script type="text/javascript">
//onblur失去焦點事件,用戶離開輸入框時執行 JavaScript 代碼:
//函數1:驗證郵箱格式
function validate_username(username){
//定義正則表達式的變量:郵箱正則
var emailReg=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
//console.log(username);
if(username !="" && username.search(emailReg) != -1)
{
document.getElementById("test_user").innerHTML = "<font color='green' size='3px'>√郵箱格式正確</font>";
}else{
document.getElementById("test_user").innerHTML = "<font color='red' size='3px'>郵箱格式錯誤</font>";
}
}
//函數2:驗證密碼是否符合要求:匹配6位密碼,由數字和字母組成:
function validate_password(password){
//^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6-10}$
//測試密碼:12345y
var passwordReg=/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6}$/;
if(password != "" && password.search(passwordReg) != -1)
{
document.getElementById("test_pw").innerHTML = "<font color='green' size='3px'>√密碼格式正確</font>";
}else{
document.getElementById("test_pw").innerHTML = "<font color='red' size='3px'>密碼格式錯誤</font>";
alert("密碼有6位,由數字和字母組成!");
}
}
//函數3:驗證兩次輸入的密碼是否一樣
function validate_password2(password2){
var password = document.getElementById("password").value;
//測試:console.log(password);
//測試:console.log(password2);
if (password == ""){
document.getElementById("is_test_pw").innerHTML = "<font color='red' size='3px'>密碼不爲空</font>";
}else if(password==password2){
document.getElementById("is_test_pw").innerHTML = "<font color='green' size='3px'>√兩次輸入的密碼相同</font>";
}else{
document.getElementById("is_test_pw").innerHTML = "<font color='red' size='3px'>兩次輸入的密碼不相同</font>";
console.log("密碼有6位,由數字和字母組成!");
}
}
//函數4:驗證表單是否已經填好
function validate_form(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var password2 = document.getElementById("password2").value;
//console.log("表單填寫正確,可以正常提交!");
//這三個,如果任何一個有問題,都返回false
//[email protected] 12345y
var emailReg=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
var passwordReg=/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6}$/;
if(username != "" && emailReg.test(username)){
if(password !="" && passwordReg.test(password)){
if(password2==password){
alert("信息填寫正確,可以正常提交!");
console.log("信息填寫正確,可以正常提交!");
return true;
}else{
alert("密碼不一致,提交失敗,請重新填寫!");
console.log("密碼不一致,提交失敗,請重新填寫!");
return false;
}
}else{
alert("密碼格式錯誤,提交失敗,請重新填寫!");
console.log("密碼格式錯誤,提交失敗,請重新填寫!");
return false;
}
}else{
alert("註冊的賬號不符合要求,提交失敗,請重新填寫!");
console.log("註冊的賬號不符合要求,提交失敗,請重新填寫!");
return false;
}
}
</script>
<body>
<div id="user_reg">用戶註冊:</div>
<form action="{%url 'user:onRegister'%}" method="post" name="form" >
<table>
<tr>
<td>請輸入用戶名:</td>
<td><input type="text" id="username" name="name" placeholder="只能用郵箱註冊" onblur="validate_username(this.value)"/></td>
<td id="test_user"></td>
</tr>
<tr>
<td>請輸入密碼:</td>
<td><input type="password" id="password" name="password" placeholder="6位密碼由數字和字母組成" onblur="validate_password(this.value)"/></td>
<td id="test_pw"></td>
</tr>
<tr>
<td>請確認密碼:</td>
<td><input type="password" id="password2" name="password2" onblur="validate_password2(this.value)" /></td>
<td id="is_test_pw"></td>
</tr>
<tr>
<td></td>
<td ><input type="submit" id="submit_form" value="註冊" onclick="return validate_form()"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</form>
</body>
</html>
6. 用戶登錄
<head>
<meta charset="UTF-8">
<title>登錄</title>
<style>
body {
background: #353f42;
}
* {
padding: 0;
margin: 0;
}
.main {
margin: 0 auto;
padding-left: 25px;
padding-right: 25px;
padding-top: 15px;
width: 350px;
height: 350px;
background: #FFFFFF;
/*以下css用於讓登錄表單垂直居中在界面,可刪除*/
position: absolute;
top: 50%;
left: 50%;
margin-top: -175px;
margin-left: -175px;
}
.title {
width: 100%;
height: 40px;
line-height: 40px;
}
.title span {
font-size: 18px;
color: #353f42;
}
.title-msg {
width: 100%;
height: 64px;
line-height: 64px;
}
.title:hover {
cursor: default;
}
.title-msg:hover {
cursor: default;
}
.title-msg span {
font-size: 12px;
color: #707472;
}
.input-content {
width: 100%;
height: 120px;
}
.input-content input {
width: 330px;
height: 40px;
border: 1px solid #dad9d6;
background: #ffffff;
padding-left: 10px;
padding-right: 10px;
}
.enter-btn {
width: 350px;
height: 40px;
color: #fff;
background: #0bc5de;
line-height: 40px;
text-align: center;
border: 0px;
}
.foor {
width: 100%;
height: auto;
color: #9b9c98;
font-size: 12px;
margin-top: 20px;
}
.enter-btn:hover {
cursor: pointer;
background: #1db5c9;
}
.foor div:hover {
cursor: pointer;
color: #484847;
font-weight: 600;
}
.left {
float: left;
}
.right {
float: right;
}
</style>
</head>
<body>
<div class="main">
<div class="title">
<span>密碼登錄</span>
</div>
<div class="title-msg">
<span>請輸入登錄賬戶和密碼</span>
</div>
<form class="login-form" action="{%url 'user:login'%}" method="post" novalidate>
<!--輸入框-->
<div class="input-content">
<!--autoFocus-->
<div>
<input type="text" autocomplete="off"
placeholder="用戶名" name="user" required/>
</div>
<div style="margin-top: 16px">
<input type="password"
autocomplete="off" placeholder="登錄密碼" name="password" required maxlength="32"/>
</div>
</div>
<!--登入按鈕-->
<div style="text-align: center">
<button type="submit" class="enter-btn">
<a href="{%url 'items:index' %}">登錄</a>
</button>
</div>
</form>
</div>
</body>
七、Django的視圖層
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt
from data.cartItems import context as cartContext
# from data.itemList import context as itemContext
from user.models import UserList
def register(request):
return render(request, 'user/register.html')
@csrf_exempt
def login(request):
if request.method == "POST":
userName = request.POST.get('user', None)
password = request.POST.get('password', None)
message = "所有字段都必須填寫!"
if userName and password: # 確保用戶名和密碼都不爲空
username = userName.strip()
# 用戶名字符合法性驗證
# 密碼長度驗證
# 更多的其它驗證.....
try:
user = UserList.objects.get(name=userName)
if user.password == password:
request.session['user'] = user.name
return redirect('/')
else:
message = "密碼不正確!"
except:
message = "用戶名不存在!"
return render(request, 'user/login.html', {"message": message})
return render(request, 'user/login.html')
@csrf_exempt
def onRegister(request):
username = request.POST.get('name', None)
password = request.POST.get('password', None)
UserList.objects.create(name=username,password=password)
return render(request, 'user/login.html')
這裏給出資源下載的地址,歡迎三連。