Stars y Opinion se incluyeron en ListItem

Esto porque al final eran relaciones 1 a 1 y era preferible que
estuvieran incluidos en un solo modelo, de esta forma hay menos llamadas
a la base de datos desde la api y una api mas simple de realizar y
llamar

Realmente el unico modelo que quedo "extraño" es el de opinion helpfull
que tendra que pasar a ser ... listitemhelpful? pero el nombre
opinionhelpful es mas coherente
This commit is contained in:
Daniel Cortes
2020-07-14 10:31:32 -04:00
parent 1a36bec50a
commit ce76f76dfb
5 changed files with 52 additions and 42 deletions

View File

@@ -12,7 +12,7 @@ class EntityForm(forms.ModelForm):
class ListItemForm(forms.ModelForm): class ListItemForm(forms.ModelForm):
class Meta: class Meta:
model = ListItem model = ListItem
fields = ['entity', 'tags'] fields = ['entity', 'tags', 'stars', 'opinion']
class TagForm(forms.ModelForm): class TagForm(forms.ModelForm):

View File

@@ -1,6 +1,7 @@
# Generated by Django 3.0.7 on 2020-06-28 22:41 # Generated by Django 3.0.7 on 2020-07-14 14:27
from django.conf import settings from django.conf import settings
import django.core.validators
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
@@ -25,33 +26,17 @@ class Migration(migrations.Migration):
name='ListItem', name='ListItem',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('stars', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(5)])),
('opinion', models.TextField(default='')),
('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.Entity')), ('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.Entity')),
], ],
), ),
migrations.CreateModel(
name='Opinion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('opinion_text', models.TextField()),
('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.ListItem')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Tag', name='Tag',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)), ('name', models.CharField(max_length=50)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tags', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Stars',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quantity', models.IntegerField()),
('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.ListItem')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
@@ -59,14 +44,14 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vote', models.CharField(choices=[('Y', 'Si'), ('N', 'No'), ('F', 'Divertida')], max_length=1)), ('vote', models.CharField(choices=[('Y', 'Si'), ('N', 'No'), ('F', 'Divertida')], max_length=1)),
('opinion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.Opinion')), ('opinion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lists.ListItem')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
), ),
migrations.AddField( migrations.AddField(
model_name='listitem', model_name='listitem',
name='tags', name='tags',
field=models.ManyToManyField(to='lists.Tag'), field=models.ManyToManyField(blank=True, related_name='list', to='lists.Tag'),
), ),
migrations.AddField( migrations.AddField(
model_name='listitem', model_name='listitem',

View File

@@ -1,4 +1,6 @@
"""Definición de los modelos que utilizara la aplicación Lists""" """Definición de los modelos que utilizara la aplicación Lists"""
from django.core.validators import MinValueValidator, MaxValueValidator
from users.models import User from users.models import User
from django.db.models import CharField, TextField, IntegerField from django.db.models import CharField, TextField, IntegerField
from django.db.models import ForeignKey, ManyToManyField from django.db.models import ForeignKey, ManyToManyField
@@ -29,25 +31,15 @@ class Tag(Model):
class ListItem(Model): class ListItem(Model):
"""Item de la lista de un usuario""" """Item de la lista de un usuario"""
stars_validators = [MinValueValidator(0), MaxValueValidator(5)]
user = ForeignKey(User, on_delete=CASCADE, related_name='list') user = ForeignKey(User, on_delete=CASCADE, related_name='list')
entity = ForeignKey(Entity, on_delete=CASCADE) entity = ForeignKey(Entity, on_delete=CASCADE)
stars = IntegerField(default=0, validators=stars_validators, blank=True)
opinion = TextField(default='', blank=True)
tags = ManyToManyField(Tag, related_name='list', blank=True) tags = ManyToManyField(Tag, related_name='list', blank=True)
class Stars(Model):
"""Estrellas que un usuario le asigno a una entidad"""
user = ForeignKey(User, on_delete=CASCADE)
entity = ForeignKey(ListItem, on_delete=CASCADE)
quantity = IntegerField()
class Opinion(Model):
"""Opinion de un usuario sobre una entidad"""
user = ForeignKey(User, on_delete=CASCADE)
entity = ForeignKey(ListItem, on_delete=CASCADE)
opinion_text = TextField()
class OpinionHelpful(Model): class OpinionHelpful(Model):
"""Voto sobre una opinion""" """Voto sobre una opinion"""
VOTES = [ VOTES = [
@@ -57,5 +49,5 @@ class OpinionHelpful(Model):
] ]
user = ForeignKey(User, on_delete=CASCADE) user = ForeignKey(User, on_delete=CASCADE)
opinion = ForeignKey(Opinion, on_delete=CASCADE) opinion = ForeignKey(ListItem, on_delete=CASCADE)
vote = CharField(max_length=1, choices=VOTES) vote = CharField(max_length=1, choices=VOTES)

View File

@@ -68,7 +68,9 @@ class TestList(TestCase):
to_add = { to_add = {
'entity': 'b', 'entity': 'b',
'entity_type': 'artist', 'entity_type': 'artist',
'tags': ['1', '2'] 'tags': ['1', '2'],
'stars': 1,
'opinion': 'oh no'
} }
response = self.client.post('/api/lists/list/1/', json.dumps(to_add), response = self.client.post('/api/lists/list/1/', json.dumps(to_add),
@@ -133,6 +135,35 @@ class TestList(TestCase):
self.assertEqual(list_item.entity_id, to_add['entity']) self.assertEqual(list_item.entity_id, to_add['entity'])
self.assertEqual(list_item.tags.count(), len(to_add['tags'])) self.assertEqual(list_item.tags.count(), len(to_add['tags']))
def test_add_to_list_non_valid_stars(self):
to_add = {
'entity': 'b',
'entity_type': 'artist',
'tags': ['1', '2'],
'stars': -1,
'opinion': 'oh no'
}
response = self.client.post('/api/lists/list/1/', json.dumps(to_add),
content_type='application/json',
HTTP_AUTHORIZATION=self._user_bearer_token())
self.assertEqual(response.status_code, 400)
to_add = {
'entity': 'b',
'entity_type': 'artist',
'tags': ['1', '2'],
'stars': 6,
'opinion': 'oh no'
}
response = self.client.post('/api/lists/list/1/', json.dumps(to_add),
content_type='application/json',
HTTP_AUTHORIZATION=self._user_bearer_token())
self.assertEqual(response.status_code, 400)
def test_delete_list_item_is_protected(self): def test_delete_list_item_is_protected(self):
response = self.client.delete('/api/lists/list/1/1/') response = self.client.delete('/api/lists/list/1/1/')
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)

View File

@@ -113,7 +113,7 @@ def list_item_view(request, user_id, list_item_id):
list_item = list_item[0] list_item = list_item[0]
if request.method == 'GET': if request.method == 'GET':
return _get_list_item(request, user, list_item) return _get_list_item(request, list_item)
if request.method == 'PUT': if request.method == 'PUT':
return _update_list_item(request, user, list_item) return _update_list_item(request, user, list_item)
elif request.method == 'DELETE': elif request.method == 'DELETE':
@@ -122,7 +122,7 @@ def list_item_view(request, user_id, list_item_id):
return JsonResponse({'status': 404, 'error': 'La ruta no existe'}, status=404) return JsonResponse({'status': 404, 'error': 'La ruta no existe'}, status=404)
def _get_list_item(request, user, list_item): def _get_list_item(request, list_item):
"""Obtiene un item de la lista del usuario""" """Obtiene un item de la lista del usuario"""
encoded_list_item = { encoded_list_item = {
@@ -133,7 +133,9 @@ def _get_list_item(request, user, list_item):
'tags': [{ 'tags': [{
'id': tag.id, 'id': tag.id,
'name': tag.name 'name': tag.name
} for tag in list_item.tags.all()] } for tag in list_item.tags.all()],
'stars': list_item.stars,
'opinion': list_item.opinion
} }
return JsonResponse(encoded_list_item) return JsonResponse(encoded_list_item)