Commit 3205232c by Matt Tuchfarber

Fix items to enable merge to master

- Fix typos
- Add "Retired" status to model for journals that aren't purchasable,
  but still viewable
- Add prefetch to serializers
- Removed 'created-by' sort for performance
- squash migration
parent f6e3a488
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
Journal Journal
======= =======
The Journal app in discovery is meant to the source of truth for most journal related information. It includes two models: Journal and JournalBundle. The Journal app in discovery is meant to be the source of truth for most journal related information. It includes two models: Journal and JournalBundle.
**Journal**: **Journal**:
The journal product is similar to a course run in the fact that it has content is linked to an organization and you can purchase/receive access to it. One notable difference is that a Journal will have an access_length, which determines the amount of time the learner will have access to it post-purchase. This is our first stage towards a subscription model. The journal product is similar to a course run in the fact that it has content, is linked to an organization, and you can purchase/receive access to it. One notable difference is that a Journal will have an access_length, which determines the amount of time the learner will have access to it post-purchase. This is our first stage towards a subscription model. Unlike a course run however, it does not have "run"s and is perpetual.
**JournalBundle**: **JournalBundle**:
The journal bundle is a collection of journals and courses. It works similar to a program in the bundling aspect, the difference lies in the fact that it doesn't necessarily constitute a progression of courses. The first (and possibly most common) use case that will use this is bundling a single course with a single journal. The journal bundle is a collection of journals and courses. It works similar to a program in the bundling aspect, the difference lies in the fact that it doesn't necessarily constitute a progression of courses. The first (and possibly most common) use case that will use this is bundling a single course with a single journal. Future options may include 1 or more courses, 1 or more journals, and/or 1 or more programs.
**Things to note**: **Things to note**:
......
...@@ -34,9 +34,16 @@ class JournalSerializer(serializers.ModelSerializer): ...@@ -34,9 +34,16 @@ class JournalSerializer(serializers.ModelSerializer):
'full_description', 'full_description',
'access_length', 'access_length',
'status', 'status',
'slug' 'slug',
) )
@classmethod
def prefetch_queryset(cls, queryset):
return queryset.select_related(
'partner',
'organization',
'currency',
)
class JournalBundleSerializer(serializers.ModelSerializer): class JournalBundleSerializer(serializers.ModelSerializer):
""" """
...@@ -55,5 +62,15 @@ class JournalBundleSerializer(serializers.ModelSerializer): ...@@ -55,5 +62,15 @@ class JournalBundleSerializer(serializers.ModelSerializer):
'partner', 'partner',
'journals', 'journals',
'courses', 'courses',
'applicable_seat_types' 'applicable_seat_types',
)
@classmethod
def prefetch_queryset(cls, queryset):
return queryset.select_related(
'partner',
).prefetch_related(
'journals',
'courses',
'applicable_seat_types',
) )
...@@ -17,7 +17,7 @@ class JournalViewSet(viewsets.ModelViewSet): ...@@ -17,7 +17,7 @@ class JournalViewSet(viewsets.ModelViewSet):
""" """
lookup_field = 'uuid' lookup_field = 'uuid'
lookup_value_regex = journal_constants.UUID_PATTERN lookup_value_regex = journal_constants.UUID_PATTERN
queryset = Journal.objects.all().order_by('-created') queryset = JournalSerializer.prefetch_queryset(Journal.objects.all())
serializer_class = JournalSerializer serializer_class = JournalSerializer
filter_backends = (DjangoFilterBackend,) filter_backends = (DjangoFilterBackend,)
filter_class = JournalFilter filter_class = JournalFilter
...@@ -32,6 +32,6 @@ class JournalBundleViewSet(CacheResponseMixin, viewsets.ReadOnlyModelViewSet): ...@@ -32,6 +32,6 @@ class JournalBundleViewSet(CacheResponseMixin, viewsets.ReadOnlyModelViewSet):
permission_classes = (IsAdminUser,) permission_classes = (IsAdminUser,)
filter_backends = (DjangoFilterBackend,) filter_backends = (DjangoFilterBackend,)
queryset = JournalBundle.objects.all() queryset = JournalBundleSerializer.prefetch_queryset(JournalBundle.objects.all())
serializer_class = JournalBundleSerializer serializer_class = JournalBundleSerializer
pagination_class = LargeResultsSetPagination pagination_class = LargeResultsSetPagination
...@@ -5,3 +5,4 @@ from djchoices import ChoiceItem, DjangoChoices ...@@ -5,3 +5,4 @@ from djchoices import ChoiceItem, DjangoChoices
class JournalStatus(DjangoChoices): class JournalStatus(DjangoChoices):
Active = ChoiceItem('active', _('Active')) Active = ChoiceItem('active', _('Active'))
Inactive = ChoiceItem('inactive', _('Inactive')) Inactive = ChoiceItem('inactive', _('Inactive'))
Retired = ChoiceItem('retired', _('Retired'))
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-06-18 16:47
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django_extensions.db.fields
import djchoices.choices
import uuid
class Migration(migrations.Migration):
replaces = [('journal', '0001_initial'), ('journal', '0002_auto_20180322_1823'), ('journal', '0003_auto_20180322_1827'), ('journal', '0004_journalbundle_partner'), ('journal', '0005_auto_20180329_2009'), ('journal', '0006_auto_20180402_2100'), ('journal', '0007_journalbundle_applicable_seat_types'), ('journal', '0006_auto_20180403_1927'), ('journal', '0008_merge_20180405_1200'), ('journal', '0009_auto_20180405_1203'), ('journal', '0010_journal_status'), ('journal', '0011_journal_slug'), ('journal', '0012_auto_20180618_1646')]
initial = True
dependencies = [
('core', '0007_auto_20171004_1133'),
('course_metadata', '0080_seat_bulk_sku'),
('course_metadata', '0081_auto_20180329_0718'),
('course_metadata', '0079_enable_program_default_true'),
]
operations = [
migrations.CreateModel(
name='Journal',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')),
('title', models.CharField(blank=True, default=None, max_length=255, null=True)),
('price', models.DecimalField(decimal_places=2, default=0.0, max_digits=10)),
('sku', models.CharField(blank=True, max_length=128, null=True)),
('expires', models.DateTimeField(blank=True, null=True)),
('currency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Currency')),
('partner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Partner')),
],
options={
'abstract': False,
'get_latest_by': 'modified',
'ordering': ('-modified', '-created'),
},
),
migrations.CreateModel(
name='JournalBundle',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')),
('title', models.CharField(help_text='The user-facing display title for this Journal Bundle', max_length=255, unique=True)),
('courses', models.ManyToManyField(blank=True, to='course_metadata.Course')),
('journals', models.ManyToManyField(blank=True, to='journal.Journal')),
('partner', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.Partner')),
('applicable_seat_types', models.ManyToManyField(blank=True, to='course_metadata.SeatType')),
],
options={
'abstract': False,
'get_latest_by': 'modified',
'ordering': ('-modified', '-created'),
},
),
migrations.RemoveField(
model_name='journal',
name='expires',
),
migrations.AddField(
model_name='journal',
name='access_length',
field=models.IntegerField(default=365, help_text='number of days valid after purchase', null=True),
),
migrations.AddField(
model_name='journal',
name='card_image_url',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='journal',
name='full_description',
field=models.TextField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name='journal',
name='organization',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='course_metadata.Organization'),
preserve_default=False,
),
migrations.AddField(
model_name='journal',
name='short_description',
field=models.CharField(default=None, max_length=350),
),
migrations.AlterUniqueTogether(
name='journal',
unique_together=set([('partner', 'uuid')]),
),
migrations.AlterModelOptions(
name='journal',
options={'ordering': ('created',)},
),
migrations.AlterField(
model_name='journal',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, verbose_name='UUID'),
),
migrations.AlterField(
model_name='journal',
name='uuid',
field=models.UUIDField(verbose_name='UUID'),
),
migrations.AddField(
model_name='journal',
name='status',
field=models.CharField(choices=[('active', 'Active'), ('inactive', 'Inactive'), ('retired', 'Retired')], db_index=True, default='active', help_text='Used to determine whether journal is marketed or not.', max_length=24, validators=[djchoices.choices.ChoicesValidator({'active': 'Active', 'inactive': 'Inactive', 'retired': 'Retired'})]),
),
migrations.AddField(
model_name='journal',
name='slug',
field=models.CharField(default='', max_length=255),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name='journal',
unique_together=set([]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-06-18 16:46
from __future__ import unicode_literals
from django.db import migrations, models
import djchoices.choices
class Migration(migrations.Migration):
dependencies = [
('journal', '0011_journal_slug'),
]
operations = [
migrations.AlterField(
model_name='journal',
name='status',
field=models.CharField(choices=[('active', 'Active'), ('inactive', 'Inactive'), ('retired', 'Retired')], db_index=True, default='active', help_text='Used to determine whether journal is marketed or not.', max_length=24, validators=[djchoices.choices.ChoicesValidator({'active': 'Active', 'inactive': 'Inactive', 'retired': 'Retired'})]),
),
migrations.AlterUniqueTogether(
name='journal',
unique_together=set([]),
),
]
...@@ -42,7 +42,7 @@ class Journal(TimeStampedModel): ...@@ -42,7 +42,7 @@ class Journal(TimeStampedModel):
full_description = models.TextField(default=None, null=True, blank=True) full_description = models.TextField(default=None, null=True, blank=True)
access_length = models.IntegerField(null=True, help_text='number of days valid after purchase', default=365) access_length = models.IntegerField(null=True, help_text='number of days valid after purchase', default=365)
status = models.CharField( status = models.CharField(
help_text=_('Used to determine whether journal is marketed or not.'), help_text='Used to determine whether journal is marketed or not.',
max_length=24, max_length=24,
null=False, null=False,
blank=False, blank=False,
...@@ -53,9 +53,6 @@ class Journal(TimeStampedModel): ...@@ -53,9 +53,6 @@ class Journal(TimeStampedModel):
slug = models.CharField(max_length=255, blank=False, null=False) slug = models.CharField(max_length=255, blank=False, null=False)
class Meta: class Meta:
unique_together = (
('partner', 'uuid'),
)
ordering = ('created',) ordering = ('created',)
def __str__(self): def __str__(self):
...@@ -70,7 +67,7 @@ class JournalBundle(TimeStampedModel): ...@@ -70,7 +67,7 @@ class JournalBundle(TimeStampedModel):
verbose_name=_('UUID') verbose_name=_('UUID')
) )
title = models.CharField( title = models.CharField(
help_text=_('The user-facing display title for this Journal Bundle'), help_text='The user-facing display title for this Journal Bundle',
max_length=CHARFIELD_MAX_LENGTH, max_length=CHARFIELD_MAX_LENGTH,
unique=True unique=True
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment