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

A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Unirse a viaje

48/62
Recursos

Aportes 13

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta 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 鈥済et_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]

驴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)

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!")

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

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