diff --git a/backend/core/__init__.py b/backend/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/core/admin.py b/backend/core/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/backend/core/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/core/apps.py b/backend/core/apps.py new file mode 100644 index 00000000..8115ae60 --- /dev/null +++ b/backend/core/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core' diff --git a/backend/core/migrations/__init__.py b/backend/core/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/core/models.py b/backend/core/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/backend/core/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/core/tests.py b/backend/core/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/backend/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/core/views.py b/backend/core/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/backend/core/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/backend/drf_course/__init__.py b/backend/drf_course/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/drf_course/asgi.py b/backend/drf_course/asgi.py new file mode 100644 index 00000000..0bb087d3 --- /dev/null +++ b/backend/drf_course/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for drf_course project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_course.settings') + +application = get_asgi_application() diff --git a/backend/drf_course/settings.py b/backend/drf_course/settings.py new file mode 100644 index 00000000..035affaa --- /dev/null +++ b/backend/drf_course/settings.py @@ -0,0 +1,144 @@ +""" +Django settings for drf_course project. + +Generated by 'django-admin startproject' using Django 4.1.3. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent +SECRET_KEY = os.environ.get("SECRET_KEY") +DEBUG = int(os.environ.get("DEBUG", default=0)) +ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ") + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django_extensions', #Great packaged to access abstract models + 'django_filters', #Used with DRF + 'rest_framework', #DRF package + 'core', # New app +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'drf_course.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'drf_course.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { + 'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler', + 'DEFAULT_PARSER_CLASSES': ( + 'rest_framework_json_api.parsers.JSONParser', + ), + 'DEFAULT_RENDERER_CLASSES': ( + 'rest_framework_json_api.renderers.JSONRenderer', + 'rest_framework.renderers.BrowsableAPIRenderer' + ), + 'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata', + 'DEFAULT_FILTER_BACKENDS': ( + 'rest_framework_json_api.filters.QueryParameterValidationFilter', + 'rest_framework_json_api.filters.OrderingFilter', + 'rest_framework_json_api.django_filters.DjangoFilterBackend', + 'rest_framework.filters.SearchFilter', + ), + 'SEARCH_PARAM': 'filter[search]', + 'TEST_REQUEST_RENDERER_CLASSES': ( + 'rest_framework_json_api.renderers.JSONRenderer', + ), + 'TEST_REQUEST_DEFAULT_FORMAT': 'vnd.api+json' +} diff --git a/backend/drf_course/urls.py b/backend/drf_course/urls.py new file mode 100644 index 00000000..af9ea8bd --- /dev/null +++ b/backend/drf_course/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from django.contrib import admin +from rest_framework import routers + +router = routers.DefaultRouter() + +urlpatterns = router.urls + +urlpatterns += [ + path('admin/', admin.site.urls), +] diff --git a/backend/drf_course/wsgi.py b/backend/drf_course/wsgi.py new file mode 100644 index 00000000..66fab8d1 --- /dev/null +++ b/backend/drf_course/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for drf_course project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_course.settings') + +application = get_wsgi_application() diff --git a/backend/manage.py b/backend/manage.py new file mode 100644 index 00000000..4e3ceab4 --- /dev/null +++ b/backend/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_course.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/steps/module_1.md b/steps/module_1.md index c6fa5696..f7ce2e23 100644 --- a/steps/module_1.md +++ b/steps/module_1.md @@ -12,7 +12,6 @@ drf_course\ <--This is the root directory backend\ docker\ ... - static\ >requirements.txt steps\ ... @@ -104,7 +103,6 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ >manage.py >requirements.txt steps\ @@ -122,4 +120,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_2.md b/steps/module_2.md index 71ca8d81..d2df7126 100644 --- a/steps/module_2.md +++ b/steps/module_2.md @@ -18,7 +18,6 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ >manage.py >requirements.txt steps\ @@ -75,7 +74,7 @@ DEBUG = int(os.environ.get("DEBUG", default=0)) ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ") ``` -installed apps: Django will only know to include our new apps in the project when we register them. Open drf_course/settings.py and register the new application in INSTALLED_APPS. Replace the current settings with the following snippet. +installed apps: Django will only know to include our new app in the project when we register it. Open drf_course/settings.py and register the new application in INSTALLED_APPS. Replace the current settings with the following snippet. ``` INSTALLED_APPS = [ 'django.contrib.admin', @@ -216,7 +215,7 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ + >db.sqlite3 <--New file >manage.py >requirements.txt steps\ @@ -234,4 +233,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_3.md b/steps/module_3.md index e10eb93a..7e995758 100644 --- a/steps/module_3.md +++ b/steps/module_3.md @@ -28,7 +28,7 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -137,7 +137,7 @@ class ContactSerializer(serializers.ModelSerializer): ``` -4) ViewSets - A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create(). +4) APIView - Using the APIView class is pretty much the same as using a regular View class, as usual, the incoming request is dispatched to an appropriate handler method such as .get() or .post(). Additionally, a number of attributes may be set on the class that control various aspects of the API policy. Go ahead and paste the following code into /backend/core/views.py @@ -146,18 +146,29 @@ from json import JSONDecodeError from django.http import JsonResponse from .serializers import ContactSerializer from rest_framework.parsers import JSONParser -from rest_framework import viewsets, status +from rest_framework import views, status from rest_framework.response import Response -class ContactViewSet(viewsets.GenericViewSet): +class ContactAPIView(views.APIView): """ - A simple ViewSet for creating contact entires. + A simple APIView for creating contact entires. """ serializer_class = ContactSerializer - def create(self, request): + def get_serializer_context(self): + return { + 'request': self.request, + 'format': self.format_kwarg, + 'view': self + } + + def get_serializer(self, *args, **kwargs): + kwargs['context'] = self.get_serializer_context() + return self.serializer_class(*args, **kwargs) + + def post(self, request): try: data = JSONParser().parse(request) serializer = ContactSerializer(data=data) @@ -185,16 +196,16 @@ from rest_framework import routers router = routers.DefaultRouter() -router.register(r'contact', core_views.ContactViewSet, basename='contact') #new endpoint for '/contact/' urlpatterns = router.urls urlpatterns += [ path('admin/', admin.site.urls), + path('contact/', core_views.ContactAPIView.as_view()), ] ``` -6) Register - Go ahead and open /core/admin.py and paste in the follwing code to register the new models to the built in admin page. +6) Register - Go ahead and open /core/admin.py and paste in the following code to register the new models to the built in admin page. ``` from django.contrib import admin @@ -213,8 +224,43 @@ python manage.py makemigrations python manage.py migrate ``` -You will now be able to see the fruits of your labour at [http://localhost:8000](http://localhost:8000). ->Note: We will fully test the endpoint in the next video +8) Call our endpoints - Here are the requests we can make to our new endpoint. + +>Note: change 'localhost' to 'api' if you make the calls via Docker Decktop. + +> This will create a contact request + +curl -X POST -H "Content-type: application/json" -d '{"name": "Bobby Stearman", "message": "test", "email":"bobby@didcoding.com"}' 'http://api:8000/contact/' + +http http://api:8000/contact/ name="Bobby Stearman" message="test" email="bobby@didcoding.com" + +if it went well, you should see something like the following in your terminal. + +``` +HTTP/1.1 200 OK +Allow: POST, OPTIONS +Content-Length: 157 +Content-Type: application/vnd.api+json +Cross-Origin-Opener-Policy: same-origin +Date: Tue, 08 Nov 2022 13:22:57 GMT +Referrer-Policy: same-origin +Server: WSGIServer/0.2 CPython/3.10.8 +Vary: Accept +X-Content-Type-Options: nosniff +X-Frame-Options: DENY + +{ + "data": { + "attributes": { + "email": "bobby@didcoding.com", + "message": "test", + "name": "Bobby Stearman" + }, + "id": "b37b5fa7-7cdd-4594-961b-8489ad66fd83", + "type": "Contact" + } +} +``` *** @@ -244,10 +290,10 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ utils\ <--New directory >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -265,4 +311,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_4.md b/steps/module_4.md index 5f6e3329..4fda8c6b 100644 --- a/steps/module_4.md +++ b/steps/module_4.md @@ -29,10 +29,10 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -57,11 +57,9 @@ git pull origin module_4 ## Steps/Commands >Note: Please 'cd' into the root directory and fire up your virtual environment! -In the last module, we built a '/contact/' end point for uses to get in touch with us. It seems to work okay but let's double down on testing. +In the last module, we built a '/contact/' end point for users to get in touch with us. It seems to work okay but let's double down on testing. In this module, we will write some unit tests to test our new endpoint. -DRF comes with a built in APIClient to - 1) Unit tests - Copy the following code into /core/tests.py ``` from . models import Contact @@ -167,19 +165,12 @@ python manage.py test 3) Call API - We're ready to call the 'contact' endpoint. I like to user (Curl)[https://curl.se/] or (Httpie)[https://httpie.io/]. -You'll need to fire up Docker if you've decdied to go down the docker route. If this is the case, use the following command. ``` -docker-compose up -d --build +curl -XPOST -H "Content-type: application/json" -d '{"name": "Bobby Stearman", "message": "test", "email":"bobby@didcoding.com"}' 'http://api:8000/contact/' ``` -Now open a cli in the 'drf_course_api' container...You're now ready to us the following commands. ->Note: Change 'localhost' to 'api' if you are using docker ``` -curl -XPOST -H "Content-type: application/json" -d '{"name": "Bobby Stearman", "message": "test", "email":"bobby@didcoding.com"}' 'http://localhost:8000/contact/' -``` - -``` -http post http://localhost:8000/contact/ name='Bobby Stearman' message='This is a test' email=bobby@didcoding.com +http post http://api:8000/contact/ name='Bobby Stearman' message='This is a test' email=bobby@didcoding.com ``` @@ -190,7 +181,7 @@ python manage.py shell Now use the following command and check the database for our new entry ``` from core.models import Contact -c = Contact.objects.latest(created) +c = Contact.objects.last() c.title ``` @@ -222,10 +213,10 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -243,4 +234,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_5.md b/steps/module_5.md index cbce2355..7ee7748c 100644 --- a/steps/module_5.md +++ b/steps/module_5.md @@ -29,10 +29,10 @@ drf_course\ <--This is the root directory >settings.py >urls.py >wsgi.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -130,6 +130,7 @@ urlpatterns = router.urls urlpatterns += [ path('admin/', admin.site.urls), + path('contact/', core_views.ContactAPIView.as_view()), path('api-token-auth/', obtain_auth_token), #gives us access to token auth ] ``` @@ -168,7 +169,7 @@ class EcommerceConfig(AppConfig): ``` -5) Create a user - Go ahead and create a new superuser. This will server 2 purposes. We we gain access to the built in Django admin page and we will also create a new token. Open a new terminal and use the follwing code. +5) Create a user - Go ahead and create a new superuser. This will server 2 purposes. We we gain access to the built in Django admin page and we will also create a new token. Open a new terminal and use the following code. ``` python manage.py createsuperuser ``` @@ -178,23 +179,14 @@ Add a username, email and password. The following commands will call the API end point: - -``` -curl -XPOST -F 'username=bobby@didcoding.com' -F 'password=fredfred1' http://localhost:8000/api-token-auth/ -``` - ``` -http post http://localhost:8000/api-token-auth/ username=bobby@didcoding.com password=fredfred1 +curl -XPOST -F 'username=**your_username**' -F 'password=**your_password**' http://api:8000/api-token-auth/ ``` -These can both be used in the Docker CLI ``` -curl -XPOST -F 'username=bobby@didcoding.com' -F 'password=fredfred1' http://api:8000/api-token-auth/ +http post http://api:8000/api-token-auth/ username=**your_username** password=**your_password** ``` -``` -http post http://api:8000/api-token-auth/ username=bobby@didcoding.com password=fredfred1 -``` With any luck, you should see something that looks like the following: ``` @@ -252,10 +244,10 @@ drf_course\ <--This is the root directory >signals.py <--New file >tests.py >views.py - static\ utils\ >__init__.py - >model_abstracts.py + >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -272,4 +264,4 @@ drf_course\ <--This is the root directory >server.py ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_6.md b/steps/module_6.md index 8adb284e..5172df06 100644 --- a/steps/module_6.md +++ b/steps/module_6.md @@ -40,10 +40,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -72,9 +72,9 @@ git pull origin module_6 Lets expand on what we have already learned and create a new app and few new endpoints. This time we will use enforce token authentication. This means only authenticated users can make calls to the endpoints. -We will build an e-commerce app with an item and order endpoint. Users will be able to retreive items in the database, place and order and retreive order information. +We will build an e-commerce app with an item and order endpoint. Users will be able to retrieve items in the database, place and order and retrieve order information. -We need models, routers, serializers and viewsets! Lets not waist any time... +We need models, routers, serializers and view-sets/api-view! Let's not waist any time... 1) Model - Go ahead and open /ecommerce/models.py and paste in the following code. ``` @@ -171,7 +171,6 @@ class Order( from collections import OrderedDict from .models import Item , Order -from .exceptions import NotEnoughStockException from rest_framework_json_api import serializers from rest_framework import status from rest_framework.exceptions import APIException @@ -187,7 +186,7 @@ class NotEnoughStockException(APIException): -class ItemSerializer(serializers.HyperlinkedModelSerializer): +class ItemSerializer(serializers.ModelSerializer): class Meta: model = Item @@ -200,7 +199,7 @@ class ItemSerializer(serializers.HyperlinkedModelSerializer): -class OrderSerializer(serializers.HyperlinkedModelSerializer): +class OrderSerializer(serializers.ModelSerializer): item = serializers.PrimaryKeyRelatedField(queryset = Item.objects.all(), many=False) @@ -283,10 +282,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -304,4 +303,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_7.md b/steps/module_7.md index 9f6c1b46..4afbcf34 100644 --- a/steps/module_7.md +++ b/steps/module_7.md @@ -41,10 +41,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -151,7 +151,6 @@ from rest_framework.authtoken.views import obtain_auth_token router = routers.DefaultRouter() -router.register(r'contact', core_views.ContactViewSet, basename='contact') router.register(r'item', ecommerce_views.ItemViewSet, basename='item') router.register(r'order', ecommerce_views.OrderViewSet, basename='order') @@ -159,6 +158,7 @@ urlpatterns = router.urls urlpatterns += [ path('admin/', admin.site.urls), + path('contact/', core_views.ContactAPIView.as_view()), path('api-token-auth/', obtain_auth_token), ] ``` @@ -202,10 +202,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -223,4 +223,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +*** diff --git a/steps/module_8.md b/steps/module_8.md index 118501cf..d54bd255 100644 --- a/steps/module_8.md +++ b/steps/module_8.md @@ -41,10 +41,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -225,52 +225,50 @@ Let's make some calls to our new endpoint. 3) Call our endpoints - Here are the requests we can make to our new endpoints. ->Note: change 'localhost' to 'api' if you make the calls via Docker Decktop. - > This retrieves the auth token for **your_username** -curl -X POST -F 'username=**your_username**' -F 'password=**your_password**' http://localhost:8000/api-token-auth/ +curl -X POST -F 'username=**your_username**' -F 'password=**your_password**' http://api:8000/api-token-auth/ -http post http://localhost:8000/api-token-auth/ username=**your_username** password=**mypassword** +http post http://api:8000/api-token-auth/ username=**your_username** password=**your_password** > This will retrieve all items -curl -X GET -H 'Authorization: Token **your_token**' http://localhost:8000/item/ +curl -X GET -H 'Authorization: Token **your_token**' http://api:8000/item/ -http http://localhost:8000/item/ 'Authorization: Token **your_token**' +http http://api:8000/item/ 'Authorization: Token **your_token**' > This will retreive a single item -curl -X GET -H 'Authorization: Token **your_token**' http://localhost:8000/item/**your_item_uuid**/ +curl -X GET -H 'Authorization: Token **your_token**' http://api:8000/item/**your_item_uuid**/ -http http://localhost:8000/item/**your_item_uuid**/ 'Authorization: Token **your_token**' +http http://api:8000/item/**your_item_uuid**/ 'Authorization: Token **your_token**' > This retrieve all orders -curl -X GET -H 'Authorization: Token **your_token**' http://localhost:8000/order/ +curl -X GET -H 'Authorization: Token **your_token**' http://api:8000/order/ -http http://localhost:8000/order/ 'Authorization: Token **your_token**' +http http://api:8000/order/ 'Authorization: Token **your_token**' > This will place an order for item id = **your_item_uuid** quantity = 1 -curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Token **your_token**' -d '{"item": "**your_item_uuid**", "quantity": "1"}' http://localhost:8000/order/ +curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Token **your_token**' -d '{"item": "**your_item_uuid**", "quantity": "1"}' http://api:8000/order/ http http://api:8000/order/ 'Authorization: Token **your_token**' item="**your_item_uuid**" quantity="1" > This get order id = **your_order_uuid** -curl -X GET -H 'Authorization: Token **your_token**' http://localhost:8000/order/**your_order_uuid**/ +curl -X GET -H 'Authorization: Token **your_token**' http://api:8000/order/**your_order_uuid**/ -http http://localhost:8000/order/**your_order_uuid**/ 'Authorization: Token **your_token**' +http http://api:8000/order/**your_order_uuid**/ 'Authorization: Token **your_token**' > This will create a contact request -curl -X POST -H "Content-type: application/json" -d '{"name": "Bobby Stearman", "message": "test", "email":"bobby@didcoding.com"}' 'http://localhost:8000/contact/' +curl -X POST -H "Content-type: application/json" -d '{"name": "Bobby Stearman", "message": "test", "email":"bobby@didcoding.com"}' 'http://api:8000/contact/' -http http://localhost:8000/contact/ name="Bobby Stearman" message="test" email="bobby@didcoding.com" +http http://api:8000/contact/ name="Bobby Stearman" message="test" email="bobby@didcoding.com" Congratulations!! You have a fully functioning and tested API!! @@ -313,10 +311,10 @@ drf_course\ <--This is the root directory >signals.py >tests.py >views.py - static\ utils\ >__init__.py >model_abstracts.py + >db.sqlite3 >manage.py >requirements.txt steps\ @@ -334,4 +332,4 @@ drf_course\ <--This is the root directory ``` *** -*** \ No newline at end of file +***