1. 程式人生 > >Django商城專案筆記No.16使用者部分-使用者中心收貨地址

Django商城專案筆記No.16使用者部分-使用者中心收貨地址

首先完成省市區三級聯動

新建areas應用

python ../../manage.py startapp areas

模型類程式碼

class Area(models.Model):
    """
    行政區劃
    """
    name = models.CharField(max_length=20, verbose_name='名稱')
    parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subs', null=True, blank=True, verbose_name='
上級行政區劃') class Meta: db_table = 'tb_areas' verbose_name = '行政區劃' verbose_name_plural = '行政區劃' def __str__(self): return self.name

模型類程式碼說明:

parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subs', null=True, blank=True, verbose_name='上級行政區劃

')

self:自關聯

on_delete=models.SET_NULL 在刪除父級的時候,自己的parent_id設定為空,這裡就不在級聯刪除了,避免誤刪除,採集資料不容易。

related_name=’subs’ 這個跟flaskbackref很類似。 意思為如果想找自己的子級,就可以通過area.subs找到自己下級所有的area區域。

之後配置應用

然後遷移資料庫

python manage.py makemigrations
python manage.py migrate

匯入測試資料指令碼

增加執行許可權

返回省市區資料的後端檢視集實現

 

定義檢視最終如下

採用檢視集

序列化器

定義路由

DRF快取的實現

 省市區的資料是經常被使用者查詢使用的,而且資料基本不變化,所以我們可以將省市區資料進行快取處理,減少資料庫的查詢次數。

在Django REST framework中使用快取,可以通過drf-extensions擴充套件來實現。

關於擴充套件使用快取的文件,可參考連結http://chibisov.github.io/drf-extensions/docs/#caching

 安裝

pip install drf-extensions

使用方法

配置檔案

禁止分頁

前端程式碼

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>美多商城-使用者中心</title>
    <link rel="stylesheet" type="text/css" href="css/reset.css">
    <link rel="stylesheet" type="text/css" href="css/main.css">
    <script type="text/javascript" src="js/host.js"></script>
    <script type="text/javascript" src="js/vue-2.5.16.js"></script>
    <script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
    <script>
        var user_id = sessionStorage.user_id || localStorage.user_id;
        var token = sessionStorage.token || localStorage.token;
        if (!(user_id && token)) {
            location.href = '/login.html?next=/user_center_site.html';
        }
    </script>
</head>
<body>
    <div id="app" v-cloak>
    <div class="header_con">
        <div class="header">
            <div class="welcome fl">歡迎來到美多商城!</div>
            <div class="fr">
                <div class="login_btn fl">
                    歡迎您:<em>{{ username }}</em>
                    <span>|</span>
                    <a @click="logout">退出</a>
                </div>
                <div class="user_link fl">
                    <span>|</span>
                    <a href="user_center_info.html">使用者中心</a>
                    <span>|</span>
                    <a href="cart.html">我的購物車</a>
                    <span>|</span>
                    <a href="user_center_order.html">我的訂單</a>
                </div>
            </div>
        </div>        
    </div>

    <div class="search_bar clearfix">
        <a href="index.html" class="logo fl"><img src="images/logo.png"></a>
        <div class="sub_page_name fl">|&nbsp;&nbsp;&nbsp;&nbsp;使用者中心</div>
        <form method="get" action="/search.html" class="search_con fr mt40">
            <input type="text" class="input_text fl" name="q" placeholder="搜尋商品">
            <input type="submit" class="input_btn fr" name="" value="搜尋">
        </form>
    </div>

    <div class="main_con clearfix">
        <div class="left_menu_con clearfix">
            <h3>使用者中心</h3>
            <ul>
                <li><a href="user_center_info.html">· 個人資訊</a></li>
                <li><a href="user_center_order.html">· 全部訂單</a></li>
                <li><a href="user_center_site.html" class="active">· 收貨地址</a></li>
                <li><a href="user_center_pass.html">· 修改密碼</a></li>
            </ul>
        </div>
        <div class="right_content clearfix"> 
                <div class="site_top_con">
                    <a @click="show_add">新增收貨地址</a>
                    <span>您已建立了<b>{{addresses.length}}</b>個收貨地址,最多可建立<b>{{ limit }}</b></span>
                </div>
                <div class="site_con" v-for="(address, index) in addresses">
                    <div class="site_title">
                        <div v-if="is_set_title[index]">
                            <input v-model="input_title" type="text" name="">
                            <input @click="save_title(index)" type="button" name="" value="保 存">
                            <input @click="cancel_title(index)" type="reset" name="" value="取 消">
                        </div>
                        <div v-else>
                            <h3>{{ address.title }}</h3>
                            <a @click="show_edit_title(index)"></a>
                        </div>    
                        <em v-if="address.id==default_address_id">預設地址</em>                        
                        <span @click="del_address(index)">×</span>
                    </div>
                    <ul class="site_list">
                        <li><span>收貨人:</span><b>{{ address.receiver }}</b></li>
                        <li><span>所在地區:</span><b>{{ address.province }} {{address.city}} {{ address.district }}</b></li>
                        <li><span>地址:</span><b>{{ address.place }}</b></li>
                        <li><span>手機:</span><b>{{ address.mobile }}</b></li>
                        <li><span>固定電話:</span><b>{{ address.tel }}</b></li>
                        <li><span>電子郵箱:</span><b>{{ address.email }}</b></li>
                    </ul>
                    <div class="down_btn">
                        <a v-if="address.id!=default_address_id" @click="set_default(index)">設為預設</a>
                        <a @click="show_edit(index)">編輯</a>
                    </div>
                </div>
        </div>
    </div>
    <div class="footer">
        <div class="foot_link">
            <a href="#">關於我們</a>
            <span>|</span>
            <a href="#">聯絡我們</a>
            <span>|</span>
            <a href="#">招聘人才</a>
            <span>|</span>
            <a href="#">友情連結</a>        
        </div>
        <p>CopyRight © 2016 北京美多商業股份有限公司 All Rights Reserved</p>
        <p>電話:010-****888    京ICP備*******8號</p>
    </div>

    <div class="pop_con" v-show="is_show_edit">
        <div class="site_con site_pop">
                <div class="site_pop_title">
                    <h3 v-if="editing_address_index">編輯收貨地址</h3>
                    <h3 v-else>新增收貨地址</h3>
                    <a @click="is_show_edit=false">×</a>
                </div>                
                <form>
                    <div class="form_group">
                        <label>*收貨人:</label>
                        <input v-model="form_address.receiver" @blur="check_receiver" type="text" name="">
                        <span v-show="error_receiver" class="error_tip">請填寫收件人</span>
                    </div>
                    <div class="form_group">
                        <label>*所在地區:</label>
                        <select v-model="form_address.province_id">
                            <option v-for="province in provinces" v-bind:value="province.id">{{ province.name }}</option>
                        </select>
                        <select v-model="form_address.city_id">
                            <option v-for="city in cities" v-bind:value="city.id">{{ city.name }}</option>
                        </select>
                        <select v-model="form_address.district_id">
                            <option v-for="district in districts" v-bind:value="district.id">{{ district.name }}</option>
                        </select>
                    </div>
                    <div class="form_group">
                        <label>*詳細地址:</label>
                        <input v-model="form_address.place" @blur="check_place" type="text" name="">
                        <span v-show="error_place" class="error_tip">請填寫地址資訊</span>
                    </div>
                    <div class="form_group">
                        <label>*手機:</label>
                        <input v-model="form_address.mobile" @blur="check_mobile" type="text" name="">
                        <span v-show="error_mobile" class="error_tip">手機資訊有誤</span>
                    </div>
                    <div class="form_group">
                        <label>固定電話:</label>
                        <input v-model="form_address.tel" type="text" name="">
                    </div>
                    <div class="form_group">
                        <label>郵箱:</label>
                        <input v-model="form_address.email" @blur="check_email" type="text" name="">
                        <span v-show="error_email" class="error_tip">郵箱資訊有誤</span>
                    </div>
                    <input @click="save_address" type="button" name="" value="保 存" class="info_submit">
                    <input @click="is_show_edit=false" type="reset" name="" value="取 消" class="info_submit info_reset">
                </form>
        </div>
        <div class="mask"></div>
    </div>
    </div>
    <script type="text/javascript" src="js/user_center_site.js"></script>
</body>
</html>
View Code

js程式碼

var vm = new Vue({
    el: '#app',
    data: {
        host: host,
        user_id: sessionStorage.user_id || localStorage.user_id,
        token: sessionStorage.token || localStorage.token,
        username: sessionStorage.username || localStorage.username,
        is_show_edit: false,
        provinces: [],
        cities: [],
        districts: [],
        addresses: [],
        limit: '',
        default_address_id: '',
        form_address: {
            receiver: '',
            province_id: '',
            city_id: '',
            district_id: '',
            place: '',
            mobile: '',
            tel: '',
            email: '',
        },
        error_receiver: false,
        error_place: false,
        error_mobile: false,
        error_email: false,
        editing_address_index: '', // 正在編輯的地址在addresses中的下標,''表示新增地址
        is_set_title: [],
        input_title: ''
    },
    mounted: function(){
        axios.get(this.host + '/areas/', {
                responseType: 'json'
            })
            .then(response => {
                this.provinces = response.data;
            })
            .catch(error => {
                alert(error.response.data);
            });
    },
    watch: {
        'form_address.province_id': function(){
            if (this.form_address.province_id) {
                axios.get(this.host + '/areas/'+ this.form_address.province_id + '/', {
                        responseType: 'json'
                    })
                    .then(response => {
                        this.cities = response.data.subs;
                    })
                    .catch(error => {
                        console.log(error.response.data);
                        this.cities = [];
                    });
            }
        },
        'form_address.city_id': function(){
            if (this.form_address.city_id){
                axios.get(this.host + '/areas/'+ this.form_address.city_id + '/', {
                        responseType: 'json'
                    })
                    .then(response => {
                        this.districts = response.data.subs;
                    })
                    .catch(error => {
                        console.log(error.response.data);
                        this.districts = [];
                    });
            }
        }
    },
    methods: {
        // 退出
        logout: function(){
            sessionStorage.clear();
            localStorage.clear();
            location.href = '/login.html';
        },
        clear_all_errors: function(){
            this.error_receiver = false;
            this.error_mobile = false;
            this.error_place = false;
            this.error_email = false;
        },
        // 展示新增地址介面
        show_add: function(){
            this.clear_all_errors();
            this.editing_address_index = '';
            this.form_address.receiver = '';
            this.form_address.province_id = '';
            this.form_address.city_id = '';
            this.form_address.district_id = '';
            this.form_address.place = '';
            this.form_address.mobile = '';
            this.form_address.tel = '';
            this.form_address.email = '';
            this.is_show_edit = true;
        },
        // 展示編輯地址介面
        show_edit: function(index){
            this.clear_all_errors();
            this.editing_address_index = index;
            // 只獲取資料,防止修改form_address影響到addresses資料
            this.form_address = JSON.parse(JSON.stringify(this.addresses[index]));
            this.is_show_edit = true;
        },
        check_receiver: function(){
            if (!this.form_address.receiver) {
                this.error_receiver = true;
            } else {
                this.error_receiver = false;
            }
        },
        check_place: function(){
            if (!this.form_address.place) {
                this.error_place = true;
            } else {
                this.error_place = false;
            }
        },
        check_mobile: function(){
            var re = /^1[345789]\d{9}$/;
            if(re.test(this.form_address.mobile)) {
                this.error_mobile = false;
            } else {
                this.error_mobile = true;
            }
        },
        check_email: function(){
            if (this.form_address.email) {
                var re = /^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$/;
                if(re.test(this.form_address.email)) {
                    this.error_email = false;
                } else {
                    this.error_email = true;
                }
            }
        },
        // 儲存地址
        save_address: function(){

        },
        // 刪除地址
        del_address: function(index){

        },
        // 設定預設地址
        set_default: function(index){

        },
        // 展示編輯標題
        show_edit_title: function(index){

        } ,
        // 儲存地址標題
        save_title: function(index){

        },
        // 取消儲存地址
        cancel_title: function(index){

        }
    }
})
View Code

測試