---
# System prepended metadata

title: Django REST Framework
tags: [Django, REST]

---

# 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
```    

