Creando el directorio.
mkdir django-rest-prj && cd django-rest-prjInstalando pipenv
pip install --user pipenvCreando estructura pipenv
pipenv --threeInstalando django, django-rest-framework y ply
pipenv install django djangorestframework plyActivar entorno virtual
pipenv shellCreando el proyecto
django-admin startproject project && cd projectCreando aplicación
django-admin startapp app_nameAñadiendo la app creada y rest_framework para que django las use.
# ./project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # django rest framework
'app', # aplicación creada
]# app/models.py
from django.db import models
class Sentence(models.Model):
# Código de entrada
input_code = models.CharField(max_length=100)
# Resultado arrojado por el parser
output_code = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{} => {}".format(self.input_code, self.output_code)creando el archivo serializers.py
touch serializers.pycreando el serializer para la clase Sentence
# app/serializers.py
from rest_framework import serializers
from app.models import Sentence
class SentenceSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = ('id', 'name', 'email', 'message')serializer para todos los campos del modelo
class SentenceSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = '__all__'# app/views.py
from app.models import Sentence
from app.serializers import SenteneSerializer
from rest_framework import generics
class SentenceListCreate(generics.ListCreateAPIView):
queryset = Lead.objects.all()
serializer_class = LeadSerializerListCreateAPIView provee los métodos GET y POST, para sobrescribirlos se crean funciones.
class SentenceListCreate(generics.ListCreateAPIView):
queryset = Lead.objects.all()
serializer_class = LeadSerializer
def list(self):
pass
def post(self):
passAñadir rutas globales
# project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app.urls'))
]Añadir rutas de la app
# app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('api/sentence/', views.SentenceListCreate.as_view() ),
]# app/admin.py
from django.contrib import admin
from .models import Sentence
admin.site.register(Sentence)Instalando JWT
pipenv install djangorestframework-jwtAñadir JWT a la configuración de las clases de autenticación
# project/settings.py
REST_FRAMEWORK = {
# ...
# Authentication settings
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
],
#...
}Añadir configuración JWT
# project/settings.py
# ...
# JWT settings
JWT_AUTH = {
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_response_payload_handler',
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_GET_USER_SECRET_KEY': None,
'JWT_PUBLIC_KEY': None,
'JWT_PRIVATE_KEY': None,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_ALLOW_REFRESH': False,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
'JWT_AUTH_COOKIE': None,
}
# ...Añadir configuración de las clases de permisos
# project/settings.py
REST_FRAMEWORK = {
# ...
# Permission settings
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
#...
}Importar módulos de JWT y de permisos en views.py
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from rest_framework_jwt.settings import api_settings
from rest_framework import permissions
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLERAñadir serializer del token
class TokenSerializer(serializers.Serializer):
token = serializers.CharField(max_length=255)Añadir vista de login para la autenticación mediante JWT
class LoginView(generics.CreateAPIView):
"""
POST auth/login/
"""
permission_classes = (permissions.AllowAny,) # Esta linea añade permisos sobre la
# Vista, en este caso permite el
# acceso a todos
queryset = User.objects.all() # Objeto que será usado para realizar las
# Operaciones sobre el objeto
def post(self, request, *args, **kwargs):
username = request.data.get("username", "")
password = request.data.get("password", "")
user = authenticate(request, username=username, password=password)
if user is not None:
# Se guarda el usuario en las sessiones de django rest
login(request, user)
serializer = TokenSerializer(data={
# se genera el token
"token": jwt_encode_handler(
jwt_payload_handler(user)
)})
serializer.is_valid()
return Response(serializer.data)
return Response(status=status.HTTP_401_UNAUTHORIZED)Para indicarle a la vista que solo puede acceder usuarios autenticados se puede usar:
permission_classes = (permissions.IsAuthenticated,)Creando user personalizado añadiendo campos adicionales
# app/models.py
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
is_coder = models.BooleanField(default=False)
is_reviewer = models.BooleanField(default=False)Usando el modelo para autenticación
# project/settings.py
AUTH_USER_MODEL = 'app.User'Reemplazar imports
from django.contrib.auth.models import User
# Cambiar a
from django.contrib.auth import get_user_model
User = get_user_model()Instalar driver mysql
pipenv install mysqlclientConfigurar driver
# app/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'interpreterdb',
'USER': 'root',
'HOST': 'localhost',
'PASSWORD': ''
}
}Instalar driver mysql
pipenv install mysql-connectorConfigurar driver
# app/settings.py
DATABASES = {
'default': {
'ENGINE': 'mysql.connector.django',
'HOST': 'localhost',
'NAME': 'interpreterdb',
'USER': 'root',
'PASSWORD': '',
'OPTIONS': {
'autocommit': True,
},
}
}En muchos casos este driver saca error con nuevas versiones de django, para solucionar se debe hacer lo siguiente:
- descargar el archivo
base.pyde https://github.com/mysql/mysql-connector-python/blob/master/lib/mysql/connector/django/base.py - pegar y reemplazar el archivo
base.pydescargado envirtual_env_project\Lib\site-packages\mysql\connector\django
Compilar react app
npm run dev