【Vue+DRF生鲜电商】24.用户收货地址功能

专题:Vue+Django REST framework前后端分离生鲜电商

Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。
Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket
Django版本:2.2、djangorestframework:3.9.2。

更多内容请点击 我的博客 查看,欢迎来访。

用户收货地址功能

对于收货地址,需要实现收货地址的增、删、改、查,所以需要继承的类有mixins.ListModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet,而这些类也可以合并为一个viewsets.ModelViewSet,点击去就可以看到继承关系:

BLOG_20190629_221125_50

用户收货地址视图AddressViewSet

编辑 apps/user_operation/views.py

class AddressViewSet(viewsets.ModelViewSet):
    """
    收货地址管理
    list:
        获取收货地址
    create:
        添加收货地址
    update:
        更新收货地址
    delete:
        删除收货地址
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 用户必须登录才能访问
    authentication_classes = (JWTAuthentication, SessionAuthentication)  # 配置登录认证:支持JWT认证和DRF基本认证

permission_classesauthentication_classes直接复制上面的即可,因为也需要用户登录认证才能完成的。

用户收货地址序列化AddressSerializer

在前端上,用户的收货地址分为省市区

BLOG_20190629_221116_22

而之前我们定义的models中定义是不够的,原来的models为:

class UserAddress(models.Model):
    """
    用户收货地址
    """
    user = models.ForeignKey(User, verbose_name='用户', help_text='用户', on_delete=models.CASCADE, related_name='addresses')
    district = models.CharField(max_length=100, default='', verbose_name='区域', help_text='区域')
    address = models.CharField(max_length=200, default='', verbose_name='收货地址', help_text='收货地址')
    signer_name = models.CharField(max_length=20, default='', verbose_name='签收人', help_text='签收人')
    signer_mobile = models.CharField(max_length=11, verbose_name='联系电话', help_text='联系电话')
    add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '收货地址'

    def __str__(self):
        return self.address

所以需要进行修改,添加provincecity两个字段

class UserAddress(models.Model):
    """
    用户收货地址
    """
    user = models.ForeignKey(User, verbose_name='用户', help_text='用户', on_delete=models.CASCADE, related_name='addresses')
    province = models.CharField(max_length=100, default='', verbose_name='省份', help_text='省份')
    city = models.CharField(max_length=100, default='', verbose_name='城市', help_text='城市')
    district = models.CharField(max_length=100, default='', verbose_name='区域', help_text='区域')
    address = models.CharField(max_length=200, default='', verbose_name='收货地址', help_text='收货地址')
    signer_name = models.CharField(max_length=20, default='', verbose_name='签收人', help_text='签收人')
    signer_mobile = models.CharField(max_length=11, verbose_name='联系电话', help_text='联系电话')
    add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '收货地址'

    def __str__(self):
        return self.address

添加完成后一定要执行makemigrationsmigrate

编写收货地址序列化类,编辑 apps/user_operation/serializers.py 添加

from .models import UserFav, UserLeavingMessage, UserAddress


class AddressSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()  # 表示user为隐藏字段,默认为获取当前登录用户
    )

    class Meta:
        model = UserAddress
        fields = ('id', 'user', 'province', 'city', 'district', 'address', 'signer_name', 'signer_mobile')

完善用户收货地址视图AddressViewSet

添加序列化类AddressSerializer

from .serializers import UserFavSerializer, UserFavListSerializer, UserLeavingMessageSerializer, AddressSerializer
from .models import UserFav, UserLeavingMessage, UserAddress


class AddressViewSet(viewsets.ModelViewSet):
    """
    收货地址管理
    list:
        获取收货地址
    create:
        添加收货地址
    update:
        更新收货地址
    delete:
        删除收货地址
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 用户必须登录才能访问
    authentication_classes = (JWTAuthentication, SessionAuthentication)  # 配置登录认证:支持JWT认证和DRF基本认证
    queryset = UserAddress.objects.all()
    serializer_class = AddressSerializer

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

注册收货地址url

编辑 DjangoOnlineFreshSupermarket/urls.py ,注册address这个url

from user_operation.views import UserFavViewSet, UserLeavingMessageViewSet, AddressViewSet


router.register(r'address', AddressViewSet, base_name='address')  # 用户收货地址

查看Server是否已经重启。

DRF Docs中测试address功能

访问 http://127.0.0.1:8000/docs/#address 可以看到新增的API

BLOG_20190629_221104_70

create中创建一个收货地址

BLOG_20190629_221058_96

添加完信息后,点击Send Request,就可以在右上角看到返回的数据

list中点击Send Request就可以看到返回的列表信息

BLOG_20190629_221050_36

Vue中收货地址接口联调

api放在 src/api/api.js 中

//添加收货地址
export const addAddress = params => {
    return axios.post(`${local_host}/address/`, params)
};

//删除收货地址
export const delAddress = addressId => {
    return axios.delete(`${local_host}/address/` + addressId + '/')
};

//修改收货地址
export const updateAddress = (addressId, params) => {
    return axios.patch(`${local_host}/address/` + addressId + '/', params)
};

//获取收货地址
export const getAddress = () => {
    return axios.get(`${local_host}/address/`)
};

Vue收获地址管理的页面在 src/views/member/receive.vue 中

当进入这个组件后,会调用getReceiveInfo()

        created() {
            this.getReceiveInfo();
        },

然后调用getAddress(),也就是请求getAddress的api

            getReceiveInfo() { //获取收件人信息
                getAddress().then((response) => {
                    //console.log(response.data);
                    this.receiveInfoArr = response.data;

                }).catch(function (error) {
                    console.log(error);
                });

            },

获取到数据之后,传递给receiveInfoArr,然后遍历得到所有地址列表

                        <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd" v-for="(item, index) in receiveInfoArr">
                            <tbody>
                            <tr>
                                <td align="right" bgcolor="#ffffff">配送区域:</td>
                                <td colspan="3" align="left" bgcolor="#ffffff">
                                    <div class="addr" @click="bubble(index)">
                                        <v-distpicker :province="item.province" :city="item.city" :area="item.district" @province="updateProvince" @city="updateCity" @area="updateArea"></v-distpicker>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">收货人姓名:</td>
                                <td align="left" bgcolor="#ffffff"><input name="consignee" type="text" class="inputBg" id="consignee_0" value="ssss" v-model="item.signer_name">
                                    <span :class="{error:item.signer_name==''}">(必填)</span>
                                </td>

                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">详细地址:</td>
                                <td align="left" bgcolor="#ffffff"><input name="address" type="text" class="inputBg" id="address_0" v-model="item.address">
                                    <span :class="{error:item.address==''}">(必填)</span></td>
                            </tr>
                            <tr>

                                <td align="right" bgcolor="#ffffff">手机:</td>
                                <td align="left" bgcolor="#ffffff"><input name="mobile" type="text" class="inputBg" id="mobile_0" v-model="item.signer_mobile"><span :class="{error:item.signer_mobile==''}">(必填)</span></td>
                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">&nbsp;</td>
                                <td colspan="3" align="center" bgcolor="#ffffff">
                                    <button class="bnt_blue_2" @click="confirmUpdate(item.id, index)">确定修改</button>
                                    <button class="bnt_blue_2" @click="deleteInfo(item.id)">删除</button>
                                </td>
                            </tr>
                            </tbody>
                        </table>

访问 http://127.0.0.1:8080/#/app/home/member/receive 可以看到前端展示的收货地址

BLOG_20190629_221038_11

Vue中新增收货地址

BLOG_20190629_221032_86

添加完成之后,可以看到列表自动刷新了

BLOG_20190629_221027_39

                        <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
                            <tbody>
                            <tr>
                                <td align="right" bgcolor="#ffffff">配送区域:</td>
                                <td colspan="3" align="left" bgcolor="#ffffff">
                                    <div class="addr">
                                        <v-distpicker :province="newInfo.province" :city="newInfo.city" :area="newInfo.district" @province="getProvince" @city="getCity" @area="getArea"></v-distpicker>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">收货人姓名:</td>
                                <td align="left" bgcolor="#ffffff"><input name="consignee" type="text" class="inputBg" id="consignee_0" value="ssss" v-model="newInfo.signer_name">
                                    <span :class="{error:newInfo.signer_name==''}">(必填)</span></td>

                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">详细地址:</td>
                                <td align="left" bgcolor="#ffffff"><input name="address" type="text" class="inputBg" id="address_0" v-model="newInfo.address">
                                    <span :class="{error:newInfo.address==''}">(必填)</span></td>
                            </tr>
                            <tr>

                                <td align="right" bgcolor="#ffffff">手机:</td>
                                <td align="left" bgcolor="#ffffff"><input name="mobile" type="text" class="inputBg" id="mobile_0" v-model="newInfo.signer_mobile"><span :class="{error:newInfo.signer_mobile==''}">(必填)</span></td>
                            </tr>
                            <tr>
                                <td align="right" bgcolor="#ffffff">&nbsp;</td>
                                <td colspan="3" align="center" bgcolor="#ffffff">
                                    <button class="bnt_blue_2" @click="addReceive">新增收货地址</button>
                                </td>
                            </tr>
                            </tbody>
                        </table>

当用户点击 新增收货地址 ,会调用addReceive()函数

            addReceive() { //提交收获信息
                addAddress(this.newInfo).then((response) => {
                    alert('添加成功');
                    // 重置新的
                    this.getReceiveInfo();
                    this.newInfo = Object.assign({}, this.newInfoEmpty);

                }).catch(function (error) {
                    console.log(error);
                });
            },

然后请求addAddressapi,请求成功后,请求getReceiveInfo()刷新收货地址列表,清空输入框

Vue中删除收货地址

当用户点击<button class="bnt_blue_2" @click="deleteInfo(item.id)">删除</button>删除时,调用deleteInfo(id, index)函数

            deleteInfo(id, index) { // 删除收获人信息
                delAddress(id).then((response) => {
                    alert('删除成功');
                    this.getReceiveInfo();
                }).catch(function (error) {
                    console.log(error);
                });
            }

之后调用delAddress(id)api进行地址删除,删除成功后弹框提示,并刷新收货地址列表。

Vue中修改收货地址

当用户点击<button class="bnt_blue_2" @click="confirmUpdate(item.id, index)">确定修改</button>会调用confirmUpdate(id, index)函数

            confirmUpdate(id, index) { // 更新收获信息
                updateAddress(id, this.receiveInfoArr[index]).then((response) => {
                    alert('修改成功');
                    this.getReceiveInfo();
                }).catch(function (error) {
                    console.log(error);
                });
            },

之后调用updateAddress(id, this.receiveInfoArr[index])api进行地址更新,更新成功后弹框提示,并刷新收货地址列表。

BLOG_20190629_221015_26

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值