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所返回的