提交 85347db6 编写于 作者: C Corley

V1.6

上级 1d9b5839
...@@ -145,6 +145,7 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') ...@@ -145,6 +145,7 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# DRF配置 # DRF配置
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'], 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': [ 'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
...@@ -159,7 +160,9 @@ AUTHENTICATION_BACKENDS = [ ...@@ -159,7 +160,9 @@ AUTHENTICATION_BACKENDS = [
# JWT配置 # JWT配置
JWT_AUTH = { JWT_AUTH = {
# 过期时间 # 过期时间
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
# 刷新过期时间
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=30),
# 请求头前缀 # 请求头前缀
'JWT_AUTH_HEADER_PREFIX': 'JWT', 'JWT_AUTH_HEADER_PREFIX': 'JWT',
} }
......
...@@ -25,7 +25,7 @@ import xadmin ...@@ -25,7 +25,7 @@ import xadmin
from .settings import MEDIA_ROOT from .settings import MEDIA_ROOT
from goods.views import GoodsListViewSet, CategoryViewSet from goods.views import GoodsListViewSet, CategoryViewSet
from users.views import SmsCodeViewSet, UserViewSet from users.views import SmsCodeViewSet, UserViewSet
from user_operation.views import UserFavViewSet from user_operation.views import UserFavViewSet, LeavingMessageViewSet, AddressViewSet
# Create a router and register our viewsets with it. # Create a router and register our viewsets with it.
...@@ -46,6 +46,12 @@ router.register(r'users', UserViewSet, basename='users') ...@@ -46,6 +46,12 @@ router.register(r'users', UserViewSet, basename='users')
# 配置收藏路由 # 配置收藏路由
router.register(r'userfavs', UserFavViewSet, basename='userfavs') router.register(r'userfavs', UserFavViewSet, basename='userfavs')
# 配置收藏路由
router.register(r'userfavs', UserFavViewSet, basename='userfavs')
# 配置收货地址路由
router.register(r'address', AddressViewSet, basename='address')
urlpatterns = [ urlpatterns = [
url(r'^xadmin/', xadmin.site.urls), url(r'^xadmin/', xadmin.site.urls),
url(r'^media/(?P<path>.*)$', serve, {'document_root':MEDIA_ROOT}), url(r'^media/(?P<path>.*)$', serve, {'document_root':MEDIA_ROOT}),
......
...@@ -19,4 +19,7 @@ ...@@ -19,4 +19,7 @@
先实现在DRF中使用token,再使用JSON Web Token登录,再实现短信发送和注册功能,最后实现前后端结合、完成注册功能。 先实现在DRF中使用token,再使用JSON Web Token登录,再实现短信发送和注册功能,最后实现前后端结合、完成注册功能。
#### V1.5 #### V1.5
主要实商品详情页功能,包括商品轮播图、商品信息等,还包括热卖商品的展示和收藏功能的实现。 主要实商品详情页功能,包括商品轮播图、商品信息等,还包括热卖商品的展示和收藏功能的实现。
\ No newline at end of file
#### V1.6
先开发和测试DRF自带API文档,再通过动态设置权限和序列化实现用户个人信息修改,再进行用户收藏、用户留言和用户收货地址的功能开发。
\ No newline at end of file
...@@ -15,7 +15,13 @@ class GoodsPagination(PageNumberPagination): ...@@ -15,7 +15,13 @@ class GoodsPagination(PageNumberPagination):
max_page_size = 100 max_page_size = 100
class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
'''商品列表页,并实现分页、搜索、过滤、排序''' '''
商品列表页,并实现分页、搜索、过滤、排序
list:
商品列表
retrieve:
商品详情
'''
queryset = Goods.objects.filter(is_delete=False).order_by('id') queryset = Goods.objects.filter(is_delete=False).order_by('id')
serializer_class = GoodsSerializer serializer_class = GoodsSerializer
...@@ -28,8 +34,10 @@ class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewset ...@@ -28,8 +34,10 @@ class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewset
class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
''' '''
List: 显示商品所有分类列表数据 list:
Retrieve: 获取单个商品分类详情 商品分类列表
retrieve:
商品分类详情
''' '''
queryset = GoodsCategory.objects.filter(category_type=1).filter(is_delete=False) queryset = GoodsCategory.objects.filter(category_type=1).filter(is_delete=False)
......
# Generated by Django 3.0.8 on 2020-07-30 18:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user_operation', '0004_auto_20200729_1735'),
]
operations = [
migrations.AddField(
model_name='useraddress',
name='city',
field=models.CharField(default='', max_length=50, verbose_name='城市'),
),
migrations.AddField(
model_name='useraddress',
name='province',
field=models.CharField(default='', max_length=50, verbose_name='省份'),
),
migrations.AlterField(
model_name='useraddress',
name='district',
field=models.CharField(default='', max_length=80, verbose_name='区域'),
),
migrations.AlterField(
model_name='userleavingmessage',
name='file',
field=models.FileField(help_text='上传的文件', upload_to='message/images/', verbose_name='上传的文件'),
),
]
...@@ -42,7 +42,7 @@ class UserLeavingMessage(models.Model): ...@@ -42,7 +42,7 @@ class UserLeavingMessage(models.Model):
help_text='留言类型: 1(留言), 2(投诉), 3(询问),4(售后), 5(求购)') help_text='留言类型: 1(留言), 2(投诉), 3(询问),4(售后), 5(求购)')
subject = models.CharField(max_length=80, default='', verbose_name='主题') subject = models.CharField(max_length=80, default='', verbose_name='主题')
message = models.TextField(default='', verbose_name='留言内容', help_text='留言内容') message = models.TextField(default='', verbose_name='留言内容', help_text='留言内容')
file = models.FileField(verbose_name='上传的文件', help_text='上传的文件') file = models.FileField(upload_to='message/images/', verbose_name='上传的文件', help_text='上传的文件')
add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间') add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
is_delete = models.BooleanField(default=False, verbose_name='是否删除') is_delete = models.BooleanField(default=False, verbose_name='是否删除')
...@@ -58,7 +58,9 @@ class UserLeavingMessage(models.Model): ...@@ -58,7 +58,9 @@ class UserLeavingMessage(models.Model):
class UserAddress(models.Model): class UserAddress(models.Model):
'''用户收货地址''' '''用户收货地址'''
user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL) user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
district = models.CharField(max_length=50, default='', verbose_name='区域') province = models.CharField(max_length=50, default='', verbose_name='省份')
city = models.CharField(max_length=50, default='', verbose_name='城市')
district = models.CharField(max_length=80, default='', verbose_name='区域')
address = models.CharField(max_length=100, default='', verbose_name='详细地址') address = models.CharField(max_length=100, default='', verbose_name='详细地址')
signer_name = models.CharField(max_length=20, default='', verbose_name='签收人') signer_name = models.CharField(max_length=20, default='', verbose_name='签收人')
signer_mobile = models.CharField(max_length=11, default='', verbose_name='联系电话') signer_mobile = models.CharField(max_length=11, default='', verbose_name='联系电话')
......
from rest_framework import serializers from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator from rest_framework.validators import UniqueTogetherValidator
from .models import UserFav from .models import UserFav, UserLeavingMessage, UserAddress
from goods.serializers import GoodsSerializer
class UserFavSerializer(serializers.ModelSerializer): class UserFavSerializer(serializers.ModelSerializer):
...@@ -16,4 +17,30 @@ class UserFavSerializer(serializers.ModelSerializer): ...@@ -16,4 +17,30 @@ class UserFavSerializer(serializers.ModelSerializer):
fields=['user', 'goods'], fields=['user', 'goods'],
message='请勿重复收藏' message='请勿重复收藏'
) )
] ]
\ No newline at end of file
class UserFavDetailSerializer(serializers.ModelSerializer):
goods = GoodsSerializer()
class Meta:
model = UserFav
fields = ['id', 'goods']
class LeavingMessageSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
class Meta:
model = UserLeavingMessage
fields = ['id', 'user', 'message_type', 'subject', 'message', 'file', 'add_time']
class AddressSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
class Meta:
model = UserAddress
fields = ['id', 'user', 'province', 'city', 'district', 'address', 'signer_name', 'add_time', 'signer_mobile']
\ No newline at end of file
...@@ -3,18 +3,74 @@ from rest_framework.permissions import IsAuthenticated ...@@ -3,18 +3,74 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .models import UserFav from .models import UserFav, UserLeavingMessage, UserAddress
from .serializers import UserFavSerializer from .serializers import UserFavSerializer, UserFavDetailSerializer, LeavingMessageSerializer, AddressSerializer
from utils.permissions import IsOwnerOrReadOnly from utils.permissions import IsOwnerOrReadOnly
# Create your views here. # Create your views here.
class UserFavViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): class UserFavViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
'''用户收藏''' '''
list:
用户收藏列表
create:
创建用户收藏
retrieve:
用户收藏详情
destroy:
删除用户收藏
'''
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly] permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
serializer_class = UserFavSerializer serializer_class = UserFavSerializer
authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication] authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
lookup_field = 'goods_id' lookup_field = 'goods_id'
def get_queryset(self): def get_queryset(self):
return UserFav.objects.filter(user=self.request.user, is_delete=False) return UserFav.objects.filter(user=self.request.user, is_delete=False)
\ No newline at end of file
def get_serializer_class(self):
'''动态设置序列化'''
if self.action == 'list':
return UserFavDetailSerializer
elif self.action == 'create':
return UserFavSerializer
return UserFavSerializer
class LeavingMessageViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
'''
list:
留言列表
create:
添加留言
delete:
删除留言
'''
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
serializer_class = LeavingMessageSerializer
def get_queryset(self):
return UserLeavingMessage.objects.filter(user=self.request.user, is_delete=False)
class AddressViewSet(viewsets.ModelViewSet):
'''
收货地址管理
list:
收货地址列表
create:
新建收货地址
update:
更新收货地址
delete:
删除收货地址
'''
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
serializer_class = AddressSerializer
def get_queryset(self):
return UserAddress.objects.filter(user=self.request.user, is_delete=False)
\ No newline at end of file
...@@ -71,4 +71,11 @@ class UserRegSerializer(serializers.ModelSerializer): ...@@ -71,4 +71,11 @@ class UserRegSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ['username', 'code', 'mobile', 'password'] fields = ['username', 'code', 'mobile', 'password']
\ No newline at end of file
class UserDetailSerializer(serializers.ModelSerializer):
'''用户详情序列化'''
class Meta:
model = User
fields = ['name', 'gender', 'birthday', 'email', 'mobile']
\ No newline at end of file
...@@ -4,12 +4,15 @@ from django.db.models import Q ...@@ -4,12 +4,15 @@ from django.db.models import Q
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from rest_framework import viewsets, status from rest_framework import viewsets, status
from rest_framework.mixins import CreateModelMixin from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .models import VerifyCode from .models import VerifyCode
from .serializers import SmsSerializer, UserRegSerializer from .serializers import SmsSerializer, UserRegSerializer, UserDetailSerializer
from utils.yunpian import yunpian from utils.yunpian import yunpian
...@@ -31,7 +34,11 @@ class CustomBackend(ModelBackend): ...@@ -31,7 +34,11 @@ class CustomBackend(ModelBackend):
class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet): class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet):
'''发送短信验证码''' '''
发送短信验证码
create:
新增短信验证码
'''
serializer_class = SmsSerializer serializer_class = SmsSerializer
...@@ -66,11 +73,38 @@ class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet): ...@@ -66,11 +73,38 @@ class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet):
}, status=status.HTTP_201_CREATED) }, status=status.HTTP_201_CREATED)
class UserViewSet(CreateModelMixin, viewsets.GenericViewSet): class UserViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, viewsets.GenericViewSet):
'''用户''' '''
用户
create:
新增用户
update:
修改用户
partial_update:
部分修改
retrieve:
用户详情
'''
serializer_class = UserRegSerializer serializer_class = UserRegSerializer
queryset = User.objects.filter(is_delete=False) queryset = User.objects.filter(is_delete=False)
authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication]
def get_permissions(self):
'''动态设置权限'''
if self.action == 'retrieve':
return [IsAuthenticated()]
elif self.action == 'create':
return []
return []
def get_serializer_class(self):
'''动态设置序列化'''
if self.action == 'retrieve':
return UserDetailSerializer
elif self.action == 'create':
return UserRegSerializer
return UserDetailSerializer
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
...@@ -84,4 +118,7 @@ class UserViewSet(CreateModelMixin, viewsets.GenericViewSet): ...@@ -84,4 +118,7 @@ class UserViewSet(CreateModelMixin, viewsets.GenericViewSet):
return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers) return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer): def perform_create(self, serializer):
return serializer.save() return serializer.save()
\ No newline at end of file
def get_object(self):
return self.request.user
\ No newline at end of file
...@@ -48,7 +48,7 @@ export const addFav = params => { return axios.post(`${local_host}/userfavs/`, p ...@@ -48,7 +48,7 @@ export const addFav = params => { return axios.post(`${local_host}/userfavs/`, p
//取消收藏 //取消收藏
export const delFav = goodsId => { return axios.delete(`${local_host}/userfavs/`+goodsId+'/') } export const delFav = goodsId => { return axios.delete(`${local_host}/userfavs/`+goodsId+'/') }
export const getAllFavs = () => { return axios.get(`${host}/userfavs/`) } export const getAllFavs = () => { return axios.get(`${local_host}/userfavs/`) }
//判断是否收藏 //判断是否收藏
export const getFav = goodsId => { return axios.get(`${local_host}/userfavs/`+goodsId+'/') } export const getFav = goodsId => { return axios.get(`${local_host}/userfavs/`+goodsId+'/') }
...@@ -67,10 +67,10 @@ export const getMessage = parmas => { return axios.post(`${host}/code/`, parmas) ...@@ -67,10 +67,10 @@ export const getMessage = parmas => { return axios.post(`${host}/code/`, parmas)
//获取用户信息 //获取用户信息
export const getUserDetail = () => { return axios.get(`${host}/users/1/`) } export const getUserDetail = () => { return axios.get(`${local_host}/users/1/`) }
//修改用户信息 //修改用户信息
export const updateUserInfo = params => { return axios.patch(`${host}/users/1/`, params) } export const updateUserInfo = params => { return axios.patch(`${local_host}/users/1/`, params) }
//获取订单 //获取订单
...@@ -84,22 +84,22 @@ export const getOrderDetail = orderId => {return axios.get(`${host}/orders/`+ord ...@@ -84,22 +84,22 @@ export const getOrderDetail = orderId => {return axios.get(`${host}/orders/`+ord
//获取留言 //获取留言
export const getMessages = () => {return axios.get(`${host}/messages/`)} export const getMessages = () => {return axios.get(`${local_host}/messages/`)}
//添加留言 //添加留言
export const addMessage = params => {return axios.post(`${host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})} export const addMessage = params => {return axios.post(`${local_host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})}
//删除留言 //删除留言
export const delMessages = messageId => {return axios.delete(`${host}/messages/`+messageId+'/')} export const delMessages = messageId => {return axios.delete(`${local_host}/messages/`+messageId+'/')}
//添加收货地址 //添加收货地址
export const addAddress = params => {return axios.post(`${host}/address/`, params)} export const addAddress = params => {return axios.post(`${local_host}/address/`, params)}
//删除收货地址 //删除收货地址
export const delAddress = addressId => {return axios.delete(`${host}/address/`+addressId+'/')} export const delAddress = addressId => {return axios.delete(`${local_host}/address/`+addressId+'/')}
//修改收货地址 //修改收货地址
export const updateAddress = (addressId, params) => {return axios.patch(`${host}/address/`+addressId+'/', params)} export const updateAddress = (addressId, params) => {return axios.patch(`${local_host}/address/`+addressId+'/', params)}
//获取收货地址 //获取收货地址
export const getAddress = () => {return axios.get(`${host}/address/`)} export const getAddress = () => {return axios.get(`${local_host}/address/`)}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册