# Django REST Framework ###### tags: `Django` `REST` # 零、參考文件 [關於 Django REST framework 的一些筆記](https://blog.m157q.tw/posts/2018/01/07/django-rest-framework-note/) [encode/django-rest-framework](https://github.com/encode/django-rest-framework) [manosim/django-rest-framework-docs](https://github.com/manosim/django-rest-framework-docs) [Django REST framework](https://www.django-rest-framework.org/) [Document Web APIs made with Django REST Framework.](https://www.drfdocs.com/) [twtrubiks/django-rest-framework-tutorial](https://github.com/twtrubiks/django-rest-framework-tutorial) [Day 19: 關於 Django REST framework 的一些筆記](https://ithelp.ithome.com.tw/articles/10196385) [How to write an API in 3 lines of code with Django REST framework](https://medium.com/crowdbotics/how-to-write-an-api-in-3-lines-of-code-with-django-rest-framework-59b0971edfa4) > 這篇講一些概念 [Let’s build an API with Django REST Framework](https://medium.com/backticks-tildes/lets-build-an-api-with-django-rest-framework-32fcf40231e5) [Creating a Django API using Django Rest Framework APIView](https://medium.com/the-andela-way/creating-a-django-api-using-django-rest-framework-apiview-b365dca53c1d) > 這篇利用 Class based View - ``APIView``實作``GET``/``POST``/``PUT``/``DELETE`` [Creating a DjangoRest API using DjangoRestFramework part 2.](https://medium.com/the-andela-way/creating-a-djangorest-api-using-djangorestframework-part-2-1231fe949795) > 介紹``GenericAPIView``, 若在 List, Detail顯示需求之下, 若使用 ``ListAPIView`` 就不必寫 ``get()`` 若使用 ``CreateAPIView`` 就不用寫 ``post()`` ``ListCreateAPIView`` 可以取代 ``CreateAPIView`` + ``ListAPIView``, 同時支讀取看與更新列表資料; 顯示Detail (單一資料用)有: > - ``RetrieveUpdateAPIView`` 同時支讀取看與更新 > - ``RetrieveAPIView``只有讀取 [Building an API with Django REST Framework and Class-Based Views ](https://codeburst.io/building-an-api-with-django-rest-framework-and-class-based-views-75b369b30396) [Official Django REST Framework Tutorial - A Beginners Guide](https://wsvincent.com/official-django-rest-framework-tutorial-beginners-guide/) [Django Rest Framework - Blog API](https://wsvincent.com/django-rest-framework-tutorial/) [Speed up Django Nested Foreign Key Serializers w/ prefetch_related](https://medium.com/quant-five/speed-up-django-nested-foreign-key-serializers-w-prefetch-related-ae7981719d3f) [Dealing with unique constraints in nested serializers](https://medium.com/django-rest-framework/dealing-with-unique-constraints-in-nested-serializers-dade33b831d9) [Nested Relationships in Serializers for OneToOne fields in Django Rest Framework](https://medium.freecodecamp.org/nested-relationships-in-serializers-for-onetoone-fields-in-django-rest-framework-bdb4720d81e6) # 常用的 classes/ code snippet ### Url 區塊: 在 ``urlpatterns`` 陣列中,透過 ``path()``,存取 ``view.index`` ``` urlpatterns = [ path('', views.index, name='index'), ] ``` ### model: #### Django ``` from django.db import models from pygments.lexers import get_all_lexers from pygments.styles import get_all_styles LEXERS = [item for item in get_all_lexers() if item[1]] LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS]) STYLE_CHOICES = sorted((item, item) for item in get_all_styles()) class Foo(models.Model): #definition of fields: question_text = models.CharField(max_length=200) title = models.CharField(max_length=100, blank=True, default='') language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100) style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100) pub_date = models.DateTimeField('date published') created = models.DateTimeField(auto_now_add=True) votes = models.IntegerField(default=0) # RefObject is other model class refObject = models.ForeignKey(RefObject, on_delete=models.CASCADE) #author = models.ForeignKey(Author, related_name='articles', on_delete=models.CASCADE) description = models.TextField() email = models.EmailField() linenos = models.BooleanField(default=False) class Meta: ordering = ('created',) def __str__(self): return self.question_text def was_published_recently(self): return self.pub_date >= timezone.now() - datetime.timedelta(days=1) ``` ### Serializer #### Django Rest Framework ``` from rest_framework import serializers class ArticleSerializer(serializers.Serializer): title = serializers.CharField(max_length=120) description = serializers.CharField() body = serializers.CharField() author_id = serializers.IntegerField() def create(self, validated_data): return Article.objects.create(**validated_data) def update(self, instance, validated_data): instance.title = validated_data.get('title', instance.title) instance.description = validated_data.get('description', instance.description) instance.body = validated_data.get('body', instance.body) instance.author_id = validated_data.get('author_id', instance.author_id) instance.save() return instance class ArticleSerializer2(serializers.ModelSerializer): class Meta: model = Article fields = ('id', 'title', 'description', 'body', 'author_id') ``` ### View #### 1. Django: 有原生的 ``View``嗎? ---> 目前尚未 subclass 過! #### 2. Django Rest Framework: ##### ``APIView``: ``` from rest_framework.views import APIView class ArticleView(APIView): # HTTP GET def get(self, request): #articles = Article.objects.all() #return Response({"articles": articles}) # the many param informs the serializer that it will be serializing more than a single article. # what does 'many=true' mean? serializer = ArticleSerializer(articles, many=True) return Response({"articles": serializer.data}) # HTTP POST def post(self, request): article = request.data.get('article') # Create an article from the above data serializer = ArticleSerializer(data=article) # what does 'raise_exception=true' mean? if serializer.is_valid(raise_exception=True): article_saved = serializer.save() return Response({"success": "Article '{}' created successfully".format(article_saved.title)}) def put(self, request, pk): saved_article = get_object_or_404(Article.objects.all(), pk=pk) data = request.data.get('article') serializer = ArticleSerializer(instance=saved_article, data=data, partial=True) if serializer.is_valid(raise_exception=True): article_saved = serializer.save() return Response({"success": "Article '{}' updated successfully".format(article_saved.title)}) def delete(self, request, pk): # Get object with this pk article = get_object_or_404(Article.objects.all(), pk=pk) article.delete() return Response({"message": "Article with id `{}` has been deleted.".format(pk)},status=204) ``` ##### ``GenericAPIView``: ``` from rest_framework.generics import get_object_or_404, GenericAPIView from rest_framework.mixins import ListModelMixin, CreateModelMixin class ArticleView2(ListModelMixin, CreateModelMixin, GenericAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer2 def get(self, request, *args, **kwargs): print("goes through ArticleView2") #involve .list() method return self.list(request, *args, *kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) def perform_create(self, serializer): author = get_object_or_404(Author, id=self.request.data.get('author_id')) return serializer.save(author=author) ``` ##### ``RetrieveUpdateAPIView`` / ``RetrieveAPIView``: ``` from rest_framework.generics import RetrieveUpdateAPIView, RetrieveAPIView class SingleArticleView(RetrieveUpdateAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer2 ```