recipes_api/README3.md
devfzn 40bbaff60b
creación TAG API
test, model, list, serializers, views & urls
2023-10-10 00:08:52 -03:00

5.0 KiB

Tags API

  • Añadir capadidad de agregar tags a las recetas
  • Creación del modelo para los tags
  • Añadir endpoints para la API tag
  • Actualizar el endpoint recipe, para agregar y listar tags

Tag endpoint

  • /api/recipe/tags
    Método HTTP Función
    POST Crear tag
    PUT/PATCH Actualizar tag
    DELETE Borrar tag
    GET Listar tags disponibles

Test Tag Model

core/tests/test_models.py

...

def create_user(email='user@example.com', password='testpass123'):
    """Create and return a new user."""
    return get_user_model().objects.create_user(email, password)
    ...

    def test_create_tag(self):
        """Test creating a tag is sucessfull."""
        user = create_user()
        tag = models.Tag.objects.create(user=user, name='Tag1')

        self.assertEqual(str(tag), tag.name)

Tag Model

  • name Nombre del tag a crear
  • user Usuario creador/dueño del tag

core/models.py

...

class Recipe(models.Model):
    """Recipe object."""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    time_minutes = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=2, blank=True)
    link = models.CharField(max_length=255, blank=True)
    tags = models.ManyToManyField('Tag')  # <--- Nueva linea

    def __str__(self):
        return self.title


class Tag(models.Model):
    """Tag for filtering recipes."""
    name = models.CharField(max_length=255)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )

    def __str__(self):
        return self.name

Crear migraciones

docker compose run --rm app sh -c python manage.py makemigrations

[+] Creating 1/0
  Container recipes_api_django-db-1  Running  0.0s
Migrations for 'core':
  core/migrations/0003_tag_recipe_tags.py
    - Create model Tag
    - Add field tags to recipe

Registrar aplicación tag en el administador

app/core/admin.py

admin.site.register(models.Tag) 

Test tags API

recipe/tests/test_tags_api.py

...

TAGS_URL = reverse('recipe:tag-list')

def create_user(email='user@example.com', password='testpass123'):
    """Create and return a user."""
    return get_user_model().objects.create_user(email=email, password=password)

class PublicTagsApiTests(TestCase):
    """Test unauthenticated API requests."""

    def setUp(self):
        self.client = APIClient()

    def test_auth_required(self):
        """Test auth is required for retriveing tags."""
        res = self.client.get(TAGS_URL)

        self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED)


class PrivateTagsApiTests(TestCase):
    """Test authenticated API requests."""

    def setUp(self):
        self.user = create_user()
        self.client = APIClient()
        self.client.force_authenticate(self.user)

    def test_retrieve_tags(self):
        """Test retrieving a list of tags."""
        Tag.objects.create(user=self.user, name='Vegan')
        Tag.objects.create(user=self.user, name='Omnivore')

        res = self.client.get(TAGS_URL)

        tags = Tag.objects.all().order_by('-name')
        serializer = TagSerializer(tags, many=True)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data, serializer.data)

    def test_tags_limited_to_user(self):
        """Test list of tags is limited to authenticated user."""
        user2 = create_user(email='user2@example.com')
        Tag.objects.create(user=user2, name='Fruity')
        tag = Tag.objects.create(user=self.user, name='Carnivore')

        res = self.client.get(TAGS_URL)

        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(len(res.data), 1)
        self.assertEqual(res.data[0]['name'], tag.name)
        self.assertEqual(res.data[0]['id'], tag.id)

Serializador Tag API

recipe/serializers.py

...

class TagSerializer(serializers.ModelSerializer):
    """Serializer for tags."""

    class Meta:
        model = Tag
        fields = ['id', 'name']
        read_only_fields = ['id']

Views tags APIs

recipe/views.py

...

class TagViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """Manage tags in the database."""
    serializer_class = serializers.TagSerializer
    queryset = Tag.objects.all()
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        """Filter queryset to authenticated user."""
        return self.queryset.filter(user=self.request.user).order_by('-id')

URLS tags APIs

recipe/urls.py

...
router.register('recipes', views.RecipeViewSet)
router.register('tags', views.TagViewSet)
...

Test Update Tags