DRF(Django REST framework)是一个高度封装的框架,这致使想完成一件事情能够经过重写父类函数的方式从DRF的各个层次来写,都可以实现目的。前端
好比写视图函数,能够用继承APIView的方式或者继承Viewsets的方式,甚至直接写视图函数python
可是想要更加干净简洁的代码,仍是须要找到实现的最佳方式数据库
如下是个人一些我的总结,欢迎讨论django
models.py
1.PositiveSmallIntegerField后端
二、字段定义中verbose_name定义的是django自带接口ui的字段说明,help_text定义的是swagger的字段说明数组
三、tag = models.ForeignKey(Tag, related_name="project_tag")框架
四、user = models.ForeignKey(User, unique=True)函数
五、ImageField和FileField其实是CharFieldsui
serializers.py
一、serializers中对字段作出的限制只会影响前端传到后端的数据,而不会影响后端传到前端的数据rest
例如
class MySerializer(serializers.ModelSerializer): TYPE = ( # (0, "级别一"), #在model中这行没有注释掉 (1, "级别二"), (2, "级别三") ) # 这样能够限制前端不能传my_type=0的数据,可是my_type=0的数据能够在前端接收到 my_type = ChoiceField(choices=TYPE,required=True)
二、通常来讲,update和create的操做都会在serializers中实现
不少刚开始接触DRF的同窗会习惯在view中写update和create,其实,在serializers中实现是一种更好的方法,
由于,这样你的代码不用绕来绕去。不用费劲获取serializer的值再费劲存到serializer里,直接在serializer中实现就好了。
别看create和update函数的源码那么长,其实不用管它们,整个重写就行了
def create(self, validated_data): ... return instance def update(self, instance, validated_data): ... return instance
validated_data是通过验证的前端数据,instance是用id获取的对应数据库数据的模型实例
它们都要返回一个模型实例,做为返回前端的数据
self.context["request"]
至关于view中的self.request
Model1.objects.create(user=self.context["request"].user, foreign_key=foreign_key_instance)
for key in update_data: setattr(instance, key, update_data[key]) # 把对象转为字典,做为新建数据的参数 dic = instance.__dict__ del dic['id'] del dic['_state'] new_instance = Model1.objects.create(**dic)
先把更新后的实例对象转为字典,再删掉id等在数据表插入新数据时不应传的数据,再将字典做为objects.create的参数
其实有一个更巧妙的方法
instance.id = None for attr, value in update_data.items(): setattr(instance, attr, value) instance.save()
instance.save()以后,instance将会变成新插入数据的模型实例
super(Model1Serializer, self).update(instance, validated_data)
views.py
一、perform_create中的serializer.save()语句能够带参数,好比
user_id = self.request.user.id serializer.save(user=User.objects.get(id=user_id))
实现从request中获取user的值,而不是从表单
二、尽可能使用objects.filter而不是get
get().delete()
会报错,filter则会取出一个空数组,不会报错三、过滤器的使用
def get_queryset(self): key_1 = self.request.key1 key_2 = self.request.key2 my_type = self.request.query_params.get('type', None) if my_type == 1: return Model.objects.filter(foreign_key_1=key_1) elif my_type == 2: return Model.objects.filter(foreign_key_2=key_2) # 默认状况,返回全部 return Model.objects.all()
其实这就是一个根据查询参数过滤的过程,彻底可使用过滤器实现,这样在Django自带ui中也会有过滤器的说明
pip install django-filter
python2要特别指定django-filter==1.1
INSTALLED_APPS
中加上django_filters
class MyFilter(django_filters.rest_framework.FilterSet): MY_TYPE = ( (1, "类别一"), (2, "类别二") ) type = django_filters.ChoiceFilter(help_text="类型", label="类型", choices=MY_TYPE, method="type_filter" ) def type_filter(self,queryset,name,value): key_1 = self.request.key1 key_2 = self.request.key2 if value == 1: return queryset.filter(foreign_key_1=key_1) elif value == 2: return queryset.filter(foreign_key_2=key_2) class Meta: model = Tag fields = ['type']
filter_backends = (DjangoFilterBackend, ) filter_class = MyFilter
而get_queryset函数只须要一句return Model.objects.all()
就好
注意type_filter的queryset就是get_queryset所返回的