マーケット・アドレスの管理

39772 ワード

宅配返品機能の実装


Frontend


lib/api/address.py
import axios from 'axios';

const client = axios.create();

export const removeAddress = (id) => {
    return client.delete(`/members/address/${id}/detail/`, {
        headers: {
            Authorization: `Token ${sessionStorage.getItem('token')}`,
        },
    });
};
lib/loading.py
import { createAction, handleActions } from 'redux-actions';

const START_LOADING = 'loading/START_LOADING';
const FINISH_LOADING = 'loading/FINISH_LOADING';

export const startLoading = createAction(
    START_LOADING,
    (requestType) => requestType,
);

export const finishLoading = createAction(
    FINISH_LOADING,
    (requestType) => requestType,
);

const initialState = {};

const loading = handleActions(
    {
        [START_LOADING]: (state, action) => ({
            ...state,
            [action.payload]: true,
        }),
        [FINISH_LOADING]: (state, action) => ({
            ...state,
            [action.payload]: false,
        }),
    },
    initialState,
);
export default loading;

lib/createRequestSaga.py

import { call, put } from 'redux-saga/effects';
import { startLoading, finishLoading } from '../modules/loading';

export const createRequestActionTypes = (type) => {
    const SUCCESS = `${type}_SUCCESS`;
    const FAILURE = `${type}_FAILURE`;
    return [type, SUCCESS, FAILURE];
};

export default function createRequestSaga(type, request) {
    const SUCCESS = `${type}_SUCCESS`;
    const FAILURE = `${type}_FAILURE`;

    return function* (action) {
        yield put(startLoading(type));
        try {
            const response = yield call(request, action.payload);
            console.log(response.data)
            yield put({
                type: SUCCESS,
                payload: response.data,
            });
        } catch (e) {
            yield put({
                type: FAILURE,
                payload: e,
                error: true,
            });
        }
        yield put(finishLoading(type));
    };
}

modules/address.py

import { createAction, handleActions } from 'redux-actions';
import { takeLatest } from 'redux-saga/effects';
import * as addressAPI from '../lib/api/address';
import createRequestSaga, {
    createRequestActionTypes,
} from '../lib/createRequestSaga';


const [REMOVE_ADDRESS, REMOVE_ADDRESS_SUCCESS, REMOVE_ADDRESS_FAILURE] =
    createRequestActionTypes('address/REMOVE_ADDRESS');


export const removeAddress = createAction(REMOVE_ADDRESS, (id) => id);

const removeAddressSaga = createRequestSaga(
    REMOVE_ADDRESS,
    addressAPI.removeAddress
)

export function* addressSaga() {
    yield takeLatest(REMOVE_ADDRESS, removeAddressSaga)
}

import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router';
import CartComponent from '../../components/cart/CartComponent';
import {
    updateAddress,
} from '../../modules/address';

const CartContainer = () => {
    const dispatch = useDispatch();
    const navigate = useNavigate();
  
  const onRemoveAddress = useCallback(
        (id) => {
            try {
                dispatch(removeAddress(id));
            } catch (e) {
                console.log(e);
            }
            navigate(0);
        },
        [dispatch],
    );
  
  return (
        <CartComponent
            onRemoveAddress={onRemoveAddress}
        />
    );
};
import React from 'react';
const CartComponent = ({onRemoveAddress}) => {
  
  return (

    <button 
          className="delete-btn"
          onClick={() => onDeletePostCodeDetailInfo(id)}>삭제</button>
  )

};

Backend


url.py
path('address/<int:address_id>/detail/', AddressDetailAddressUpdateAPIView.as_view())
model.py
class UserAddress(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE, related_name='user_addresses', help_text='유저 주소')
    address = models.CharField('주소', max_length=255)
    default_address = models.BooleanField('기본배송지 여부', default=False)
    selected_address = models.BooleanField('선택된 배송지 여부', default=True)
    phone_number = models.CharField('휴대폰 주소', max_length=13, default='')
    receive_name = models.CharField('받은사람', max_length=50, default='')
    created = models.DateTimeField('주소 추가 날짜', auto_now_add=True)
    updated_at = models.DateTimeField('주소 변경 날짜', auto_now=True)
serializer.py
class UserDetailAddressUpdateSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True, required=False)

    class Meta:
        model = UserAddress
        fields = "__all__"
api.py
class AddressDetailAddressUpdateAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = UserAddress.objects.all()
    serializer_class = UserDetailAddressUpdateSerializer

    def get_object(self):
        obj = get_object_or_404(UserAddress, pk=self.kwargs.get("address_id"))
        return obj
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

    def perform_destroy(self, instance):
        queryset = self.queryset.filter(user=self.request.user)
        extra_objects = queryset.exclude(id=instance.id)
        if len(extra_objects) < 1:
            pass
        else:
            if instance.default_address and instance.selected_address:
                obj = extra_objects.first()
                obj.default_address = True
                obj.selected_address = True
                obj.save()

            elif instance.default_address and instance.selected_address is False:
                # 기본 주소지 is True && 선택 주소지 is False
                # 선택 주소지 filtering, default address 설정
                obj_filter = [add_obj for add_obj in extra_objects if add_obj.selected_address is True]
                obj = obj_filter.pop()
                obj.default_address = True
                obj.save()
            elif instance.default_address is False and instance.selected_address:
                # 기본 주소지 is False && 선택 주소지 is True
                # 선택 주소지 filtering, default address selected address = True 설정
                obj_filter = [add_obj for add_obj in extra_objects if add_obj.default_address is True]
                obj = obj_filter.pop()
                obj.selected_address = True
                obj.save()
            else:
                pass
        super().perform_destroy(instance)
アドレスを削除する場合
デフォルトアドレス(default address)と選択アドレス(selected address)を考慮して,アドレスオブジェクトを削除した後に残りの値をどのように処理するかを想定した.
まずは!!
  • が2つ以上のアドレスの場合は
  • である.
    アドレスが
  • の場合、object
  • を削除するだけです.
    a.アドレスが2個より大きい
    1)デフォルトのアドレスがあり、アドレスが真であるオブジェクトを削除します.

    結果
  • 次の索引オブジェクトのすべてのデフォルトアドレス選択アドレス値をTrueに設定
  • 2)デフォルトアドレスTrue And選択アドレスFalseのオブジェクトを削除する.

    結果
  • デフォルトアドレスがTrueの値を選択アドレスに設定
  • 3)デフォルトアドレスエラーと選択アドレスがTrueのオブジェクトを削除する.

    結果
  • 選択アドレスTrueの値をデフォルトアドレスに設定
  • 4)デフォルトアドレスと選択アドレスの両方がfalseのオブジェクトを削除します.

    結果
  • 直接除去

  • from source
    https://github.com/velopert/learning-react/