Skip to content

Commit

Permalink
this is before using a base class for testing the generic model
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewKassab committed Jul 18, 2024
1 parent d7ef509 commit da46e85
Show file tree
Hide file tree
Showing 20 changed files with 840 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
'rest_framework.authtoken',
'drf_spectacular',
'user',
'recipe',
]

MIDDLEWARE = [
Expand Down
1 change: 1 addition & 0 deletions app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@
name='api-docs',
),
path('api/user/', include('user.urls')),
path('api/recipe/', include('recipe.urls'))
]
3 changes: 3 additions & 0 deletions app/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ class UserAdmin(BaseUserAdmin):


admin.site.register(models.User, UserAdmin)
admin.site.register(models.Recipe)
admin.site.register(models.Tag)
admin.site.register(models.Ingredient)
27 changes: 27 additions & 0 deletions app/core/migrations/0002_recipe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.2.25 on 2024-06-21 23:23

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('core', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='Recipe',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255)),
('description', models.TextField(blank=True)),
('time_minutes', models.IntegerField()),
('price', models.DecimalField(decimal_places=2, max_digits=5)),
('link', models.CharField(blank=True, max_length=255)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
23 changes: 23 additions & 0 deletions app/core/migrations/0003_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.25 on 2024-07-11 23:59

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('core', '0002_recipe'),
]

operations = [
migrations.CreateModel(
name='Tag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
18 changes: 18 additions & 0 deletions app/core/migrations/0004_recipe_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2024-07-16 23:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0003_tag'),
]

operations = [
migrations.AddField(
model_name='recipe',
name='tags',
field=models.ManyToManyField(to='core.Tag'),
),
]
27 changes: 27 additions & 0 deletions app/core/migrations/0005_auto_20240717_2317.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.2.25 on 2024-07-17 23:17

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('core', '0004_recipe_tags'),
]

operations = [
migrations.CreateModel(
name='Ingredient',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='recipe',
name='ingredients',
field=models.ManyToManyField(to='core.Ingredient'),
),
]
19 changes: 19 additions & 0 deletions app/core/migrations/0006_ingredient_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.25 on 2024-07-17 23:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0005_auto_20240717_2317'),
]

operations = [
migrations.AddField(
model_name='ingredient',
name='name',
field=models.CharField(default='Eggplant', max_length=255),
preserve_default=False,
),
]
41 changes: 41 additions & 0 deletions app/core/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Database models.
"""
from django.conf import settings
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin

Expand Down Expand Up @@ -37,3 +38,43 @@ class User(AbstractBaseUser, PermissionsMixin):
objects = UserManager()

USERNAME_FIELD = 'email'


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)
link = models.CharField(max_length=255, blank=True)
tags = models.ManyToManyField('Tag')
ingredients = models.ManyToManyField('Ingredient')

def __str__(self):
return self.title


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

def __str__(self):
return self.name


class Ingredient(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)

def __str__(self):
return self.name
38 changes: 38 additions & 0 deletions app/core/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
"""
Tests for models
"""
from decimal import Decimal

from django.test import TestCase
from django.contrib.auth import get_user_model

from core import models


def create_user(email='[email protected]', password='testpass123'):
"Create and return a new user."""
return get_user_model().objects.create_user(email, password)


class ModelTests(TestCase):
"""Test models"""
Expand Down Expand Up @@ -45,3 +54,32 @@ def test_create_superuser(self):
self.assertTrue(user.is_superuser)
self.assertTrue(user.is_staff)

def test_create_recipe(self):
"""Test creating a recipe is successful."""
user = get_user_model().objects.create_user(
'[email protected]',
'testpass123',
)
recipe = models.Recipe.objects.create(
user=user,
title='Sample recipe name',
time_minutes=5,
price=Decimal('5.50'),
description='Sample recipe description',
)

self.assertEqual(str(recipe), recipe.title)

def test_create_tag(self):
user = create_user()
tag = models.Tag.objects.create(user=user, name='Tag1')

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

def test_create_ingredient(self):
user = create_user()
ingredient = models.Ingredient.objects.create(user=user, name='Eggplant')

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


Empty file added app/recipe/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions app/recipe/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class RecipeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'recipe'
62 changes: 62 additions & 0 deletions app/recipe/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
Serializers for the recipe API View.
"""
from django.utils.translation import gettext as _

from rest_framework import serializers

from core.models import Recipe, Tag


class TagSerializer(serializers.ModelSerializer):

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


class RecipeSerializer(serializers.ModelSerializer):
"""Serializer for recipes."""
tags = TagSerializer(many=True, required=False)

class Meta:
model = Recipe
fields = ['id', 'title', 'time_minutes', 'price', 'link', 'tags']
read_only_fields = ['id']

def __get_or_create_tags(self, tags, recipe):
auth_user = self.context['request'].user
for tag in tags:
tag_obj, created = Tag.objects.get_or_create(
user=auth_user,
**tag,
)
recipe.tags.add(tag_obj)

def create(self, validated_data):
"""Create a new Recipe"""
tags = validated_data.pop('tags', [])
recipe = Recipe.objects.create(**validated_data)
self.__get_or_create_tags(tags, recipe)

return recipe

def update(self, instance, validated_data):
tags = validated_data.pop('tags', None)
if tags is not None:
instance.tags.clear()
self.__get_or_create_tags(tags, instance)

for attr, value in validated_data.items():
setattr(instance, attr, value)

instance.save()
return instance


class RecipeDetailSerializer(RecipeSerializer):

class Meta(RecipeSerializer.Meta):
fields = RecipeSerializer.Meta.fields + ['description']

Empty file added app/recipe/tests/__init__.py
Empty file.
48 changes: 48 additions & 0 deletions app/recipe/tests/base_test_name_user_model_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from abc import ABC

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse

from rest_framework import status
from rest_framework.test import APIClient

def create_user(email='[email protected]', password='testpass123'):
return get_user_model().objects.create(email=email, password=password)


class BasePublicNameUserModelTests(TestCase):
model = None
url = None

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

def test_auth_required(self):
res = self.client.get(self.url)

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


class BasePrivateNameUserModelTest(TestCase):
model = None
serializer = None
url = None
detail_url_reversal = None

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

def test_retrieve_model(self):
self.model.objects.create(user=self.user, name='Vegan')
self.model.objects.create(user=self.user, name='Dessert')

res = self.client.get(self.url)

tags = self.model.objects.all().order_by('-name')
serializer = self.serializer(tags, many=True)

self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertEqual(res.data, serializer.data)
Loading

0 comments on commit da46e85

Please sign in to comment.