├── movies ├── __init__.py ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── resources ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0002_auto_20200325_1451.py │ └── 0001_initial.py ├── admin.py ├── tests.py ├── apps.py ├── models.py ├── serializers.py └── views.py ├── .gitignore ├── requirements.txt ├── manage.py ├── README.md └── requests.md /movies/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | myvenv 2 | __pycache__ 3 | *.pyc 4 | db.sqlite3 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /resources/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /resources/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.2.7 2 | Django==3.1.13 3 | djangorestframework==3.11.2 4 | pytz==2019.3 5 | sqlparse==0.3.1 6 | -------------------------------------------------------------------------------- /resources/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ResourcesConfig(AppConfig): 5 | name = 'resources' 6 | -------------------------------------------------------------------------------- /resources/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | class Filme(models.Model): 4 | titulo = models.CharField(max_length=100) 5 | diretor = models.CharField(max_length=100) 6 | sinopse = models.TextField() 7 | genero = models.CharField(max_length=100) 8 | owner = models.ForeignKey('auth.User', related_name='filmes', on_delete=models.CASCADE) 9 | 10 | def __str__(self): 11 | return self.title -------------------------------------------------------------------------------- /movies/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for movies project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'movies.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /movies/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for movies project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'movies.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /resources/migrations/0002_auto_20200325_1451.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-03-25 14:51 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('resources', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='filme', 15 | old_name='usuario', 16 | new_name='owner', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /movies/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path 3 | from resources import views as resources_views 4 | from rest_framework.authtoken.views import obtain_auth_token 5 | 6 | urlpatterns = [ 7 | path('admin/', admin.site.urls), 8 | path('filmes/', resources_views.FilmeList.as_view()), 9 | path('filmes//', resources_views.FilmeDetail.as_view()), 10 | path('usuarios/', resources_views.UserList.as_view()), 11 | path('usuarios//', resources_views.UserDetail.as_view()), 12 | path('login/', obtain_auth_token, name='api_token_auth'), 13 | ] -------------------------------------------------------------------------------- /resources/serializers.py: -------------------------------------------------------------------------------- 1 | from resources.models import Filme 2 | from django.contrib.auth.models import User 3 | from rest_framework import serializers 4 | 5 | class FilmeSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = Filme 8 | owner = serializers.ReadOnlyField(source='owner.username') 9 | fields = ['id', 'titulo', 'diretor', 'sinopse', 'genero', 'owner'] 10 | 11 | class UserSerializer(serializers.ModelSerializer): 12 | filmes = serializers.PrimaryKeyRelatedField(many=True, queryset=Filme.objects.all()) 13 | 14 | class Meta: 15 | model = User 16 | fields = ['id', 'username', 'filmes'] -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'movies.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django REST API Tutorial 2 | 3 | Neste guia vamos desenvolver uma REST API com o framework Django REST. 4 | 5 | **[Leia o Tutorial](https://akiradev.netlify.app/posts/django-rest-api/)** 6 | 7 | --- 8 | 9 | ## Instalação 10 | 11 | ### Clone o Repositório 12 | 13 | ``` 14 | git clone https://github.com/the-akira/Django-REST-Tutorial.git 15 | ``` 16 | 17 | ### Dentro do Diretório Principal 18 | 19 | Crie um Ambiente Virtual 20 | 21 | ``` 22 | python -m venv myvenv 23 | ``` 24 | 25 | Ative o Ambiente Virtual 26 | 27 | ``` 28 | source myvenv/bin/activate 29 | ``` 30 | 31 | Instale os Requeriments 32 | 33 | ``` 34 | pip install -r requirements.txt 35 | ``` 36 | 37 | Sincronize o banco de dados 38 | 39 | ``` 40 | python manage.py migrate 41 | ``` 42 | 43 | Execute a aplicação 44 | 45 | ``` 46 | python manage.py runserver 47 | ``` 48 | 49 | Faça [Requisições](https://github.com/the-akira/Django-REST-Tutorial/blob/master/requests.md). -------------------------------------------------------------------------------- /resources/views.py: -------------------------------------------------------------------------------- 1 | from resources.models import Filme 2 | from django.contrib.auth.models import User 3 | from rest_framework.permissions import IsAuthenticated 4 | from resources.serializers import FilmeSerializer, UserSerializer 5 | from rest_framework import generics 6 | 7 | class FilmeList(generics.ListCreateAPIView): 8 | queryset = Filme.objects.all() 9 | serializer_class = FilmeSerializer 10 | permission_classes = [IsAuthenticated] 11 | 12 | def perform_create(self, serializer): 13 | serializer.save(owner=self.request.user) 14 | 15 | class FilmeDetail(generics.RetrieveUpdateDestroyAPIView): 16 | queryset = Filme.objects.all() 17 | serializer_class = FilmeSerializer 18 | permission_classes = [IsAuthenticated] 19 | 20 | class UserList(generics.ListAPIView): 21 | queryset = User.objects.all() 22 | serializer_class = UserSerializer 23 | 24 | class UserDetail(generics.RetrieveAPIView): 25 | queryset = User.objects.all() 26 | serializer_class = UserSerializer -------------------------------------------------------------------------------- /resources/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-03-25 14:20 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Filme', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('titulo', models.CharField(max_length=100)), 22 | ('diretor', models.CharField(max_length=100)), 23 | ('sinopse', models.TextField()), 24 | ('genero', models.CharField(max_length=100)), 25 | ('usuario', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='filmes', to=settings.AUTH_USER_MODEL)), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /requests.md: -------------------------------------------------------------------------------- 1 | # Requests 2 | 3 | ## AUTH 4 | 5 | curl -d '{"username":"akira", "password":"5565340gabriel"}' -H "Content-Type: application/json" -X POST http://localhost:8000/login/ 6 | 7 | ## GET 8 | 9 | curl -X GET http://localhost:8000/filmes/ -H 'Authorization: Token 75c0bba76256298d8d7ea5f204cfad83fe9a174d' 10 | 11 | curl -X GET http://localhost:8000/filmes/5/ -H 'Authorization: Token d1781baac8f55daf296f6f32144ba2e107d949b5' 12 | 13 | ## POST 14 | 15 | curl -d '{"titulo":"The Lord of the Rings","diretor":"Peter Jackson","sinopse":"The Lord of the Rings is a film series of three epic fantasy adventure films directed by Peter Jackson, based on the novel written by J. R. R. Tolkien.","genero":"Adventure","owner":1}' -H "Content-Type: application/json" -X POST http://localhost:8000/filmes/ -H 'Authorization: Token 75c0bba76256298d8d7ea5f204cfad83fe9a174d' 16 | 17 | ## PUT 18 | 19 | curl -d '{"titulo":"Fight Club","diretor":"David Fincher","sinopse":"Fight Club is a 1999 American film directed by David Fincher","genero":"cult","owner":1}' -H "Content-Type: application/json" -X PUT http://localhost:5000/filmes/2/ -H 'Authorization: Token 75c0bba76256298d8d7ea5f204cfad83fe9a174d' 20 | 21 | ## DELETE 22 | 23 | curl -H "Content-Type: application/json" -X DELETE http://localhost:5000/filmes/1/ -H 'Authorization: Token 75c0bba76256298d8d7ea5f204cfad83fe9a174d' 24 | -------------------------------------------------------------------------------- /movies/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for movies project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'o+_v7em_3ea951drw%y&b2lhwzy&0n@y-l7__@)=ok8i=b1fr7' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'rest_framework.authtoken', 41 | 'rest_framework', 42 | 'resources', 43 | ] 44 | 45 | REST_FRAMEWORK = { 46 | 'DEFAULT_AUTHENTICATION_CLASSES': [ 47 | 'rest_framework.authentication.TokenAuthentication', 48 | ], 49 | } 50 | 51 | MIDDLEWARE = [ 52 | 'django.middleware.security.SecurityMiddleware', 53 | 'django.contrib.sessions.middleware.SessionMiddleware', 54 | 'django.middleware.common.CommonMiddleware', 55 | 'django.middleware.csrf.CsrfViewMiddleware', 56 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 57 | 'django.contrib.messages.middleware.MessageMiddleware', 58 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 59 | ] 60 | 61 | ROOT_URLCONF = 'movies.urls' 62 | 63 | TEMPLATES = [ 64 | { 65 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 66 | 'DIRS': [], 67 | 'APP_DIRS': True, 68 | 'OPTIONS': { 69 | 'context_processors': [ 70 | 'django.template.context_processors.debug', 71 | 'django.template.context_processors.request', 72 | 'django.contrib.auth.context_processors.auth', 73 | 'django.contrib.messages.context_processors.messages', 74 | ], 75 | }, 76 | }, 77 | ] 78 | 79 | WSGI_APPLICATION = 'movies.wsgi.application' 80 | 81 | 82 | # Database 83 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 84 | 85 | DATABASES = { 86 | 'default': { 87 | 'ENGINE': 'django.db.backends.sqlite3', 88 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 89 | } 90 | } 91 | 92 | 93 | # Password validation 94 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 95 | 96 | AUTH_PASSWORD_VALIDATORS = [ 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 102 | }, 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 105 | }, 106 | { 107 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 108 | }, 109 | ] 110 | 111 | 112 | # Internationalization 113 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 114 | 115 | LANGUAGE_CODE = 'en-us' 116 | 117 | TIME_ZONE = 'UTC' 118 | 119 | USE_I18N = True 120 | 121 | USE_L10N = True 122 | 123 | USE_TZ = True 124 | 125 | 126 | # Static files (CSS, JavaScript, Images) 127 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 128 | 129 | STATIC_URL = '/static/' 130 | --------------------------------------------------------------------------------