0. Environment
# OS
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.4
BuildVersion: 17E199
# Python
$ python --version
Python 3.6.1 :: Anaconda 4.4.0 (x86_64)
# Django
In [1]: import django
In [2]: django.get_version()
Out[2]: '2.0.6'
# rest_framework
In [1]: import rest_framework
In [2]: rest_framework.VERSION
Out[2]: '3.8.2'
1. Project set up
The following is the process of setting up project and application.
# Create project directory called 'projectdir'
$ mkdir projectdir
$ cd $_
# Set up a new project called 'testproject'
# Don't forget trailing '.' character otherwise, extra 'testproject' directory will be created
$ django-admin.py startproject testproject .
$ tree .
.
├── manage.py
└── testproject
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
1 directory, 5 files
# Set up application called 'helloworld'
$ cd testproject/
$ django-admin.py startapp helloworld
$ cd ..
$ tree .
.
├── manage.py
└── testproject
├── __init__.py
├── helloworld
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── settings.py
├── urls.py
└── wsgi.py
3 directories, 12 files
$
2. Migration
After setting up your own project according to above, you have to do migration. Migration is somehow reflecting remediation of your project to database. Before reflecting, we can confirm as is with showmigrations command.
$ python ./manage.py showmigrations
admin
[ ] 0001_initial
[ ] 0002_logentry_remove_auto_add
auth
[ ] 0001_initial
[ ] 0002_alter_permission_name_max_length
[ ] 0003_alter_user_email_max_length
[ ] 0004_alter_user_username_opts
[ ] 0005_alter_user_last_login_null
[ ] 0006_require_contenttypes_0002
[ ] 0007_alter_validators_add_error_messages
[ ] 0008_alter_user_username_max_length
[ ] 0009_alter_user_last_name_max_length
contenttypes
[ ] 0001_initial
[ ] 0002_remove_content_type_name
sessions
[ ] 0001_initial
$
Leading character [] means that these configuration has not been reflected to database. Let's reflect these information to database with migrate command.
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
$
Then, you can check whether they were reflected or not :)
$ python ./manage.py showmigrations
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial
$
We can see leading character has been changed to '[X]'. It means the information has been already reflected to the database .
3. Writing minimum logic
What I have to do is writing logic to respond "Hello World". As I have said, I will use Function Based Views.Note :
In this example, for simplicity, I will write logic on urls.py. Nevertheless, you won't write there in real project.
from rest_framework.response import Response
from rest_framework.decorators import api_view
from django.conf.urls import url, include
@api_view(['GET','POST'])
def hello_world(request):
if request.method == 'POST':
return Response({"message": "Got some data!", "data": request.data})
return Response({"message": "Hello, world!"})
urlpatterns = [
url(r'^hello/$', hello_world),
]
4. Check Functionality
Now we are ready to boot server.
$ python ./manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
July 02, 2018 - 13:09:25
Django version 2.0.6, using settings 'testproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
You can check the functionality with 'curl' command.
$ curl -X GET http://127.0.0.1:8000/hello/
{"message":"Hello, world!"}
$
Needless to say, we can respond to 'POST' data.
$ curl -X POST -F "hello=world" http://127.0.0.1:8000/hello/
{"message":"Got some data!","data":{"hello":"world"}}
$
Nice. I've also found Flask to be very small and nice to work with.
ReplyDeleteAwesome example. I found that for my basic rest api the "Set up application called 'helloworld'". step was not nessecary.
ReplyDeletethanks
ReplyDeletenice, thanks
ReplyDeleteThanks for your example, It was very usefull
ReplyDelete