Bienvenida

1

Todo lo que aprenderás sobre Django

Cimientos

2

Arquitectura de una aplicación

3

The Twelve-Factor App

4

Codebase: Settings modular

5

Codebase: Dependencias y archivos de docker

6

Codebase: Docker

7

Setups alternativos

Modelos

8

Herencia de modelos

9

Proxy models

10

App de usuarios

11

Organizando modelos en un paquete de Django

12

Creando el modelo de perfil de usuario

13

Solución del reto: arreglando la migración de users a user

14

Aplicación y modelo de círculos

15

Migraciones y admin de círculos

Introducción a Django REST Framework

16

Aprende cómo construir tu propio API con Django Rest Framework

17

Vistas, URLs y Parsers de DRF

18

Serializers

19

Buenas prácticas para el diseño de un API REST

20

Request, response, renderers y parsers

Real DRF

21

Autenticación y tipos de autenticación

22

APIView

23

Creando el token de autorización

24

User sign up

25

Limitar login a usuarios con cuenta verificada

26

Configurar envío de email

27

Instalar PyJWT y generar tokens

28

Verificar cuenta usando JWT

29

Actualizar modelo de circle (membership)

30

Crear CircleViewSet

31

Añadiendo autorización y paginación

32

Creación de circulos

33

Update de círculo, custom permissions y DRF Mixins

34

Migración de vistas de usuarios a ViewSets

35

Detalle de usuario

36

Update profile data

37

List members - Recursos anidado

38

Retrieve destroy member

39

Modelo de invitaciones y manager

40

Obtener invitaciones de un miembro

41

Unirse a grupo

42

Filtrado

43

App de rides y modelos

44

Implementar la publicación de un ride

45

Validación de campos de un serializer

46

Listado de rides

47

Editar un ride

48

Unirse a viaje

49

Terminar viaje

50

Calificar viaje

Tareas asíncronas

51

¿Qué es Celery?

52

Creando tarea asíncrona

53

Creando tarea periódica

Testing

54

Python unittest y Django TestCase

55

DRF APITestCase

Django Admin

56

Admin actions: Modificar datos de un query

57

Admin actions: Regresando una respuesta HTTP

Deployment

58

Instalación de la aplicación

59

Configuración del dominio en Mailgun y del Bucket en Amazon S3

60

Configuración final de Docker Container usando Supervisor

61

Tutorial de despliegue de la aplicación

62

Futuros pasos y cierre del curso

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Unirse a viaje

48/62
Recursos

Aportes 13

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Cuando hace la ultima validación en el método validate el profe se equivoco puesto que si tuviste un ride en cualesquier circle y quieres tomar un ride nuevo en cualquier circle este te saldrá que ya estas en el viaje sin embargo no es cierto, aquí les dejo la solución:

def validate(self, data):
        """Verify rides allow new passengers."""
        ride = self.context['ride']
        if ride.departure_date <= timezone.now():
            raise serializers.ValidationError("You can't join this ride now")

        if ride.available_seats < 1:
            raise serializers.ValidationError("Ride is already full!")

        if ride.passengers.filter(pk=self.context['user'].pk).exists():
            raise serializers.ValidationError('Passenger is already in this trip')

        return data

Otra cosa que faltó actualizar es el número de asientos disponibles. Mi forma de arreglarlo fue desde el método update del JoinRideSerializer en cride.rides.serializers.rides de esta forma

    def update(self, instance, data):
        """Add passenger to ride and updates stats"""
        ride = self.context['ride']
        user = self.context['user']

        ride.passengers.add(user)
        instance.available_seats -= 1 # Lineas que 
        instance.save()			# modifiqué

        # Profile
        profile = user.profile
        profile.rides_taken += 1
        profile.save()
	
	...

¿Qué opinan, hay otra mejor alternativa? Gracias por los aportes 😄

mi solución del reto:
permiso:

...
class IsNotRideOwner(BasePermission):
    """Verify the passenger is not owner of ride"""

    def has_object_permission(self, request, view, obj):
        """check request user doesn't equal to object"""
        return request.user != obj.offered_by
...

metodo “get_permissions”:

    def get_permissions(self):
        """
        Assign permission base on actions
        """
        permissions = [IsAuthenticated, IsActiveCircleMember]
        if self.action in ['update', 'partial_update']:
            permissions.append(IsRideOwner)
        if self.action == 'join':
            permissions.append(IsNotRideOwner)
        return [p() for p in permissions]

Aporte

No es necesario pasar ride a el contexto del serializer, ya que como es partial ya estámos mandando ride en el atributo instance del serializer.

En lugar de tener que hacer:

self.contenxt['ride`]

Debería ser solo:

self.instance

En validate_passenger, esta seria la forma de validar que el usuario no este en otro ride en 2 lineas

        if Ride.objects.filter(passengers=data,is_active=True).exists():
            raise serializers.ValidationError("User is already in an active ride!")

¿Como diferencia cuando el update es para Join y cuando es para RideModelSerializer?
Porque en el get serializer ahora con update mandamos el JoinRideSerializer pero si quiere hacer update del círculo no estaria dando el mismo serializer?

método .add() en relaciones manyToMany para agregar algo que ya ha sido salvado

Serializer Partial Update

mandando el 'ride' por contexto mediante el serializer custom

Creo que en el método get_serializer_class hay un error, debería ser if self.action == 'join': cuando se llama este método.

def get_serializer_class(self):
    """Return serializer based on actions."""
    if self.action == 'create':
        return CreateRideSerializer
    if self.action == 'join':
        return JoinRideSerializer
    return RideModelSerializer

Además tengo otra propuesta para incluir el ride en el contexto, sin eliminar la información que ya teníamos aquí (que por cierto hay mucha, usuario, vista, formato y circulo), gracias a que con esta propuesta seguimos trayendo super.get_serializer_context, tenemos más sin tener que incluirla en el método que llamamos (work smarter, not harder).

def get_serializer_context(self):
    """Add circle to serializer context."""
    context = super(RideViewset, self).get_serializer_context()
    context['circle'] = self.circle
    if self.action == 'join':
        context['ride'] = self.get_object()
    return context

@action(detail=True, methods=['POST'])
def join(self, request, *args, **kwargs):
    """Add requestiing user to ride."""
    ride = self.get_object()
    serializer = self.get_serializer(
        ride,
        data={'passenger': request.user.username},
        partial=True
    )
    serializer.is_valid(raise_exception=True)
    ride = serializer.save()

    data = RideModelSerializer(ride).data
    return Response(data, status=status.HTTP_200_OK)

🤙👍

Mi solucion al desafio fue revisar dentro de check_permissions si el valor de IsRideOwner es True, en cuyo caso llamo permission_denied. Si no es RideOwner, llamo la definicion por defecto de check_permissions().

Es como un permiso, pero al reves.

El codigo:

    def check_permissions(self, request):
        if self.action == "join":
            if IsRideOwner().has_permission(request, self):
                self.permission_denied(
                    request,
                    message="You cannot join your own ride.",
                    code="400",
                )
        super(RideViewSet, self).check_permissions(request)

Aporte - Validaciones extra

A mi parecer, falta en la lógica de negocio que un usuario no se pueda unir a un ride si está actualmente en uno y que quién ofrece el ride no se pueda unir pasajero, para esto implementé los siguiente en el validate_passenger:

# Import this at the begining of the file
from django.db.models import Q

# Validator inside of the Join Ride Serializer
def validate_passenger(self, passenger):
	...other validacions

	# Verify that the user is not who offers the ride
	if self.context['ride'].offered_by == passenger:
		raise serializers.ValidationError('Ride issuer can\'t be a passenger')

	# Verify that the passenger is not already in another ride
	is_already_in_other_ride = Ride.objects.filter(
		~Q(id=self.instance.id),
		passengers=passenger,
		is_active=True,
	).exists()
	if is_already_in_other_ride:
		raise serializers.ValidationError('Passenger is already in another ride')
	
	return passenger