[Django] Rest API 1

Django Basic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# APP models.py
from django.db import models
from django.conf import settings
# Create your models here.

def upload_update_image(instance, filename):
return "updates/{user}/{filename}".format(user=instance.user, filename=filename)


class Update(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
content = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to =upload_update_image, blank=True, null=True)
updated = models.DateTimeField(auto_now = True)
timestamp = models.DateTimeField(auto_now_add = True)

def __str__(self):
return self.content or ""

After adding new models, run python manage.py makemigrations, and then run python manage.py migrate

Register models

1
2
3
4
5
# APP admin.py
from django.contrib import admin
import updates.models as models
# Register your models here.
admin.site.register(models.Update)

JSON Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# APP views.py

from django.shortcuts import render
from django.http import JsonResponse, HttpResponse
from updates.models import Update
# It's like just returning the context dictionary rather than render it in the template with render()

def update_model_detail_view(request):
'''
Return URI
GET -- Retrieve
'''
data = {
"count": 1000,
"content": "Some new content"
}
return JsonResponse(data)

## Another way
import json
def update_model_detail_view(request):
data = {
"count": 1000,
"content": "Some new content"
}
json_data = json.dump(data)
return HttpResponse(json_data, content_type='application/json')

Class based View with Json

Reusable Mixin

1
2
3
4
5
6
7
8
9
10
# PROJECT mixins.py
from django.http import JsonResponse

class JsonResponseMixin(object):
def render_to_json_response(self, context, **response_kwargs):
# **response_kwargs are additional key-value pairs you want to set in the response
return JsonResponse(self.get_data(context), **response_kwargs)

def get_data(self, context): # can have some pre-process with context in this function
return context
1
2
3
4
5
6
7
8
9
10
11
12
13
# use Mixin class
# APP views.py
from PROJECT.mixins import JsonResponseMixin
from django.views.generic import View

class JsonCBV2(JsonResponseMixin, View):
def get(self, request, *args, **kwargs):
data = {
"count": 1000,
"content": "Some new content"
}
# This function allows us to reuse the Mixin when needed
return self.render_to_json_response(data)

[Caption] Why do we need to add as_view() in urls pattern?
Answer: https://stackoverflow.com/questions/31491028/django-generic-views-based-as-view-method

The as_view() function returns a callable view that takes a request and then returns an response. It’s the main entry-point in request-response cycle in case of generic views. And this is required in the Class Based Views in Django.

Data Serialization

Data Serialization is to convert the data into a dictionary or into a different data structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.core.serializers import serialize
class SerializedDetailView(View):
def get(self, request, *args, **kwargs):
obj = Update.objects.get(id=1);
data = serialize("json", [obj,], fields=('user','content'))
json_data = data
return HttpResponse(json_data, content_type='application/json')

class SeiralizedListView(View):
def get(self, request, *args, **kwargs):
qs = Update.objects.all()
data = serialize("json", qs, fields=('user', 'content')) # select fil
print(data)
json_data = data
return HttpResponse(json_data, content_type='application/json')

We can put the serializer into models

models.Manager: A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application.

Adding extra Manager methods is the preferred way to add “table-level” functionality to your models. (For “row-level” functionality – i.e., functions that act on a single instance of a model object)

A custom Manager method can return anything you want. It doesn’t have to return a QuerySet.

See: https://docs.djangoproject.com/en/2.1/topics/db/managers/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# APP models.py
from django.core.serializers import serialize

class UpdateQuerySet(models.QuerySet):
def serialze(self):
qs = self
return serialze('json', qs, fields=('user', 'content', 'image'))

class UpdateManager(models.Manager):
def get_queryset(self): # Serialize every returned object (row level operations)
return UpdateQuerySet(self.model, using=self._db)

class Update(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
content = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to =upload_update_image, blank=True, null=True)
updated = models.DateTimeField(auto_now = True)
timestamp = models.DateTimeField(auto_now_add = True)
objects = UpdateManager() # Use serializer before returning objects

def serialize(self): # serialize an instance
return serialize("json", [self], fields=('user', 'content', 'image'))

## OR
def serialize(self): # serialize an instance
json_data = serialize("json", [self], fields=('user', 'content', 'image'))
struct = json.loads(json_data) # turn data into dictionary and select which part of data to show
data = json.dumps(struct[0]['fields'])
return data

def __str__(self):
return self.content or ""

In the views.py

1
2
3
4
5
class SeiralizedListView(View):
def get(self, request, *args, **kwargs):
data = serialize("json", qs, fields=('user', 'content')) # select fil
json_data = Update.objects.all().serialize()
return HttpResponse(json_data, content_type='application/json')

OR models.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class UpdateQuerySet(models.QuerySet):
def serialize(self):
list_values = list(self.values("user", "content", "image"))
return json.dumps(list_values)

class Update(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
content = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to =upload_update_image, blank=True, null=True)
updated = models.DateTimeField(auto_now = True)
timestamp = models.DateTimeField(auto_now_add = True)
objects = UpdateManager() # Use serializer before returning objects

def serialize(self): # serialize an instance
try:
image = self.image.url
except:
image = ""
data = {
"content": self.content,
"user": self.user.id,
"image": image
}
data = json.dumps(data) # convert data into json
return data

def __str__(self):
return self.content or ""