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>
)
};
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)를 고려하여 주소 object를 제거 후에 어떻게 나머지 값들을 처리할지 구상하였다.
먼저!!
a. 주소가 2개 이상일 경우
1) 기본 주소지 이면서 선택 주소지가 True인 객체를 제거 할 경우
결과물
2) 기본 주소지 True AND 선택 주소지 False인 객체를 제거할 경우
결과물
3) 기본 주소지 False AND 선택 주소지 True인 객체를 제거할 경우
결과물
4) 기본 주소지 AND 선택주소지 모두 False인 객체를 제거할 경우
결과물
from source
https://github.com/velopert/learning-react/