8-1 viewset实现详情页接口
8-2 热卖商品接口实现
models中is_hot字段,使用过滤查询goods中is_hot为True的字段
goods/filter mate中加入 is_hot
import django_filters
from django.db.models import Q
from .models import Goods
class GoodsFilter(django_filters.rest_framework.FilterSet):
"""
商品的过滤类
"""
pricemin = django_filters.NumberFilter(name='shop_price', help_text="最低价格",lookup_expr='gte')
pricemax = django_filters.NumberFilter(name='shop_price', lookup_expr='lte')
top_category = django_filters.NumberFilter(method='top_category_filter')
def top_category_filter(self, queryset, name, value):
return queryset.filter(Q(category_id=value)|Q(category__parent_category_id=value)|Q(category__parent_category__parent_category_id=value))
class Meta:
model = Goods
fields = ['pricemin', 'pricemax', 'is_hot', 'is_new']
-
进入网址会有所有的api。
点击goods点击过滤器filter
8-3 用户收藏接口和实现
- 用户行为,写在user_operation/views.py下面
from rest_framework import mixins, viewsets
from user_operation.models import UserFav
from user_operation.serializers import UserFavSerializer
class UserFavViewset(mixins.CreateModelMixin,mixins.DestroyModelMixin, viewsets.GenericViewSet):
queryset = UserFav.objects.all()
serializer_class = UserFavSerializer
- user-operation/ser
from rest_framework import serializers
from user_operation.models import UserFav
__author__ = 'lv'
__date__ = '2018/1/11 12:44'
class UserFavSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = UserFav
fields = ("user","goods")
- urls
router.register(r'userfavs', UserFavViewset, base_name="userfavs")
2个字段 user,和goodsid,其中user是要服务器自己获取当前用户的。
说实话我有点小震惊,这么点代码就完成了post请求,我的天啊.
RUN:
- 打开http://localhost:8000/userfavs/ 提交商品
- 打开nvicat查看user
我是登录的,居然保存成功了.木哈哈哈
如果要做删除的功能,最好返回id字段.
user_operation/serializer.py
class UserFavSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = UserFav
fields = ("user","goods","id")
RUN:
- 删除
直接网址http://localhost:8000/userfavs/2/点击delete红钮也能删除
-
数据库:
细节优化,如果用户点击收藏过的商品,不应该重复收藏,这需要在models中类UserFavs,mate中配置unique_together = ("user", "goods")
class UserFav(models.Model):
"""
用户收藏
"""
user = models.ForeignKey(User, verbose_name="用户")
goods = models.ForeignKey(Goods, verbose_name="商品", help_text="商品id")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = '用户收藏'
verbose_name_plural = verbose_name
unique_together = ("user", "goods")
def __str__(self):
return self.user.username
这样重复点击收藏效果如下:
- 在serializers里面设置重复收藏,可以自定义错误信息
class UserFavSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = UserFav
validators = [
UniqueTogetherValidator(
queryset=UserFav.objects.all(),
fields=('user', 'goods'),
message="已经收藏"
)
]
fields = ("user", "goods", "id")
-
效果
8-4drf的权限验证
没有权限验证,会有这样一个问题,如果一个用户传送不属于他收藏的ID,就会删除其他人的收藏数据,这样就要验证他提交的ID,中的user是不是当前用户的user
token认证最好放到具体的view里面,不要放到全局之中.如果在前端请求中每一个都加入了token的认证.那么连最基础的goods页面都请求不了.
IsAuthenticated如果用户没有登录的话会抛出401
IsOwnerOrReadOnly这个权限就是验证是否是当前用户
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
这个一个是token认证,一个是session认证.
- user_operation/views.py
class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin,
mixins.DestroyModelMixin, viewsets.GenericViewSet):
"""
list:
获取用户收藏列表
retrieve:
判断某个商品是否已经收藏
create:
收藏商品
"""
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
serializer_class = UserFavSerializer
lookup_field = "goods_id"
def get_queryset(self):
return UserFav.objects.filter(user=self.request.user)
setting 去掉
# 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',utils/permission
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Instance must have an attribute named `owner`.
return obj.user == request.user
**最好补一个postman测试.
8-5 vue联调
登录情况下,都可以,
未登录有bug