Commit cb2a2dfb by Clinton Blackburn Committed by Clinton Blackburn

Publisher form cleanup

- Removed unnecessary subclassing
- Renamed BaseCourseForm to BaseForm to avoid confusion
- Removed unnecessary docstrings

LEARNER-2621
parent bc919d8d
"""Publisher API Serializers"""
import re
import waffle
from django.apps import apps
from django.db import transaction
......@@ -12,9 +13,9 @@ from rest_framework import serializers
from course_discovery.apps.core.models import User
from course_discovery.apps.publisher.choices import PublisherUserRole
from course_discovery.apps.publisher.emails import (
send_change_role_assignment_email, send_email_for_studio_instance_created, send_email_preview_accepted,
send_email_preview_page_is_available)
from course_discovery.apps.publisher.emails import (send_change_role_assignment_email,
send_email_for_studio_instance_created, send_email_preview_accepted,
send_email_preview_page_is_available)
from course_discovery.apps.publisher.models import CourseRun, CourseRunState, CourseState, CourseUserRole
......
......@@ -16,7 +16,7 @@ from course_discovery.apps.publisher.api.permissions import (CanViewAssociatedCo
from course_discovery.apps.publisher.api.serializers import (CourseRevisionSerializer, CourseRunSerializer,
CourseRunStateSerializer, CourseStateSerializer,
CourseUserRoleSerializer, GroupUserSerializer)
from course_discovery.apps.publisher.forms import CustomCourseForm
from course_discovery.apps.publisher.forms import CourseForm
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension)
from course_discovery.apps.publisher.utils import is_internal_user, is_publisher_admin
......@@ -82,7 +82,7 @@ class RevertCourseRevisionView(APIView):
history_object = get_object_or_404(historicalcourse, pk=history_id)
course = get_object_or_404(Course, id=history_object.id)
try:
for field in CustomCourseForm().fields:
for field in CourseForm().fields:
if field not in ['team_admin', 'organization', 'add_new_run']:
setattr(course, field, getattr(history_object, field))
......
"""
Course publisher forms.
"""
import html
from dal import autocomplete
......@@ -49,12 +46,10 @@ class ClearableImageInput(forms.ClearableFileInput):
template_with_clear = render_to_string('publisher/_clearImageLink.html')
class BaseCourseForm(forms.ModelForm):
""" Base Course Form. """
class BaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs.setdefault('label_suffix', '')
super(BaseCourseForm, self).__init__(*args, **kwargs)
super(BaseForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field_classes = 'field-input input-text'
if isinstance(field, forms.Textarea):
......@@ -74,19 +69,7 @@ class BaseCourseForm(forms.ModelForm):
field.widget.attrs['class'] = field_classes
class CourseForm(BaseCourseForm):
""" Course Form. """
short_description = forms.CharField(widget=forms.Textarea, max_length=255, required=False)
class Meta:
model = Course
fields = '__all__'
exclude = ('changed_by',)
class CustomCourseForm(CourseForm):
""" Course Form. """
class CourseForm(BaseForm):
organization = forms.ModelChoiceField(
queryset=Organization.objects.filter(
organization_extension__organization_id__isnull=False
......@@ -163,7 +146,7 @@ class CustomCourseForm(CourseForm):
add_new_run = forms.BooleanField(required=False)
class Meta(CourseForm.Meta):
class Meta:
model = Course
widgets = {
'image': ClearableImageInput(attrs={'accept': 'image/*'})
......@@ -190,7 +173,7 @@ class CustomCourseForm(CourseForm):
self.declared_fields['organization'].queryset = get_user_organizations(user)
self.declared_fields['team_admin'].widget.attrs = {'data-user': user.id}
super(CustomCourseForm, self).__init__(*args, **kwargs)
super(CourseForm, self).__init__(*args, **kwargs)
if user and not is_internal_user(user):
self.fields['video_link'].widget = forms.HiddenInput()
......@@ -231,17 +214,7 @@ class CourseSearchForm(forms.Form):
)
class CourseRunForm(BaseCourseForm):
""" Course Run Form. """
class Meta:
model = CourseRun
fields = '__all__'
exclude = ('state', 'changed_by',)
class CustomCourseRunForm(CourseRunForm):
""" Course Run Form. """
class CourseRunForm(BaseForm):
start = forms.DateTimeField(label=_('Course Start Date'), required=True)
end = forms.DateTimeField(label=_('Course End Date'), required=True)
staff = PersonModelMultipleChoice(
......@@ -307,16 +280,16 @@ class CustomCourseRunForm(CourseRunForm):
required=False
)
class Meta(CourseRunForm.Meta):
class Meta:
model = CourseRun
fields = (
'length', 'transcript_languages', 'language', 'min_effort', 'max_effort',
'target_content', 'pacing_type', 'video_language',
'staff', 'start', 'end', 'is_xseries', 'xseries_name', 'is_professional_certificate',
'length', 'transcript_languages', 'language', 'min_effort', 'max_effort', 'target_content', 'pacing_type',
'video_language', 'staff', 'start', 'end', 'is_xseries', 'xseries_name', 'is_professional_certificate',
'professional_certificate_name', 'is_micromasters', 'micromasters_name', 'lms_course_id',
)
def save(self, commit=True, course=None, changed_by=None): # pylint: disable=arguments-differ
course_run = super(CustomCourseRunForm, self).save(commit=False)
course_run = super(CourseRunForm, self).save(commit=False)
if course:
course_run.course = course
......@@ -363,7 +336,7 @@ class CustomCourseRunForm(CourseRunForm):
if start and end and start > end:
raise ValidationError({'start': _('Start date cannot be after the End date')})
if min_effort and max_effort and min_effort > max_effort:
raise ValidationError({'min_effort': _('Minimum effort cannot be greater than Maximum effort')})
raise ValidationError({'min_effort': _('Minimum effort cannot be greater than Maximum effort')})
if min_effort and max_effort and min_effort == max_effort:
raise ValidationError({'min_effort': _('Minimum effort and Maximum effort can not be same')})
if not min_effort and max_effort:
......@@ -379,18 +352,37 @@ class CustomCourseRunForm(CourseRunForm):
def __init__(self, *args, **kwargs):
self.is_project_coordinator = kwargs.pop('is_project_coordinator', None)
super(CustomCourseRunForm, self).__init__(*args, **kwargs)
super(CourseRunForm, self).__init__(*args, **kwargs)
if not self.is_project_coordinator:
self.fields['lms_course_id'].widget = forms.HiddenInput()
class SeatForm(BaseCourseForm):
""" Course Seat Form. """
class SeatForm(BaseForm):
def __init__(self, *args, **kwargs):
super(SeatForm, self).__init__(*args, **kwargs)
field_classes = 'field-input input-select'
if 'type' in self.errors:
field_classes = '{} has-error'.format(field_classes)
self.fields['type'].widget.attrs = {'class': field_classes}
TYPE_CHOICES = [
('', _('Choose enrollment track')),
(Seat.AUDIT, _('Audit only')),
(Seat.VERIFIED, _('Verified')),
(Seat.PROFESSIONAL, _('Professional education')),
(Seat.CREDIT, _('Credit')),
]
type = forms.ChoiceField(choices=TYPE_CHOICES, required=False, label=_('Enrollment Track'))
price = forms.DecimalField(max_digits=6, decimal_places=2, required=False, initial=0.00)
credit_price = forms.DecimalField(max_digits=6, decimal_places=2, required=False, initial=0.00)
class Meta:
fields = ('price', 'type', 'credit_price')
model = Seat
fields = '__all__'
exclude = ('currency', 'changed_by',)
def save(self, commit=True, course_run=None, changed_by=None): # pylint: disable=arguments-differ
# When seat is save make sure its prices and others fields updated accordingly.
......@@ -435,37 +427,9 @@ class SeatForm(BaseCourseForm):
seat.credit_price = 0.00
class CustomSeatForm(SeatForm):
""" Course Seat Form. """
def __init__(self, *args, **kwargs):
super(CustomSeatForm, self).__init__(*args, **kwargs)
field_classes = 'field-input input-select'
if 'type' in self.errors:
field_classes = '{} has-error'.format(field_classes)
self.fields['type'].widget.attrs = {'class': field_classes}
TYPE_CHOICES = [
('', _('Choose enrollment track')),
(Seat.AUDIT, _('Audit only')),
(Seat.VERIFIED, _('Verified')),
(Seat.PROFESSIONAL, _('Professional education')),
(Seat.CREDIT, _('Credit')),
]
type = forms.ChoiceField(choices=TYPE_CHOICES, required=False, label=_('Enrollment Track'))
price = forms.DecimalField(max_digits=6, decimal_places=2, required=False, initial=0.00)
credit_price = forms.DecimalField(max_digits=6, decimal_places=2, required=False, initial=0.00)
class Meta(SeatForm.Meta):
fields = ('price', 'type', 'credit_price')
class BaseUserAdminForm(forms.ModelForm):
"""This form will be use for type ahead search in django-admin."""
class Meta:
fields = '__all__'
widgets = {
......@@ -525,7 +489,6 @@ class PublisherUserCreationForm(forms.ModelForm):
class CourseRunAdminForm(forms.ModelForm):
class Meta:
model = CourseRun
fields = '__all__'
......
......@@ -3,9 +3,8 @@ from __future__ import unicode_literals
from django.db import migrations
from course_discovery.apps.publisher.constants import (
PARTNER_COORDINATOR_GROUP_NAME, PUBLISHER_GROUP_NAME, REVIEWER_GROUP_NAME
)
from course_discovery.apps.publisher.constants import (PARTNER_COORDINATOR_GROUP_NAME, PUBLISHER_GROUP_NAME,
REVIEWER_GROUP_NAME)
GROUPS = [PARTNER_COORDINATOR_GROUP_NAME, REVIEWER_GROUP_NAME, PUBLISHER_GROUP_NAME]
......
......@@ -4,7 +4,6 @@ from __future__ import unicode_literals
from django.db import migrations
OLD_ROLE_NAME = 'partner_coordinator'
NEW_ROLE_NAME = 'project_coordinator'
USER_ROLE_MODELS = [
......
......@@ -12,10 +12,8 @@ from course_discovery.apps.course_metadata.choices import CourseRunPacing
from course_discovery.apps.course_metadata.tests import factories
from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher.choices import PublisherUserRole
from course_discovery.apps.publisher.models import (
Course, CourseRun, CourseRunState, CourseState, CourseUserRole, OrganizationExtension, OrganizationUserRole, Seat,
UserAttributes
)
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension, OrganizationUserRole, Seat, UserAttributes)
class CourseFactory(factory.DjangoModelFactory):
......
......@@ -8,7 +8,7 @@ from course_discovery.apps.core.models import User
from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.course_metadata.models import Person
from course_discovery.apps.course_metadata.tests.factories import OrganizationFactory, PersonFactory
from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, PublisherUserCreationForm
from course_discovery.apps.publisher.forms import CourseForm, CourseRunForm, PublisherUserCreationForm
from course_discovery.apps.publisher.tests.factories import CourseFactory, OrganizationExtensionFactory
......@@ -19,7 +19,7 @@ class UserModelChoiceFieldTests(TestCase):
def setUp(self):
super(UserModelChoiceFieldTests, self).setUp()
self.course_form = CustomCourseForm()
self.course_form = CourseForm()
def test_course_form(self):
"""
......@@ -50,7 +50,7 @@ class PersonModelMultipleChoiceTests(TestCase):
"""
Verify that PersonModelMultipleChoice returns `full_name` and `profile_image_url` as choice label.
"""
course_form = CustomCourseRunForm()
course_form = CourseRunForm()
course_form.fields['staff'].empty_label = None
person = PersonFactory()
......@@ -85,7 +85,7 @@ class PublisherUserCreationFormTests(TestCase):
class PublisherCourseRunEditFormTests(TestCase):
"""
Tests for the publisher 'CustomCourseRunForm'.
Tests for the publisher 'CourseRunForm'.
"""
def test_minimum_effort(self):
......@@ -93,7 +93,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' error if Minimum effort is greater
than Maximum effort.
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'min_effort': 4, 'max_effort': 2}
with self.assertRaises(ValidationError):
run_form.clean()
......@@ -106,7 +106,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' error if Minimum effort and
Maximum effort are equal.
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'min_effort': 4, 'max_effort': 4}
with self.assertRaises(ValidationError) as err:
run_form.clean()
......@@ -120,7 +120,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' error if Minimum effort is
empty.
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'max_effort': 4}
with self.assertRaises(ValidationError) as err:
run_form.clean()
......@@ -134,7 +134,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' if the Start date is in the past
Or if the Start date is after the End date
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
current_datetime = datetime.now(timezone('US/Central'))
run_form.cleaned_data = {'start': current_datetime + timedelta(days=3),
'end': current_datetime + timedelta(days=1)}
......@@ -150,7 +150,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' if the is_xseries is checked
but no xseries_name has been entered
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'is_xseries': True, 'xseries_name': ''}
with self.assertRaises(ValidationError):
run_form.clean()
......@@ -163,7 +163,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' if the is_micromasters is checked
but no micromasters_name has been entered
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'is_micromasters': True, 'micromasters_name': ''}
with self.assertRaises(ValidationError):
run_form.clean()
......@@ -176,7 +176,7 @@ class PublisherCourseRunEditFormTests(TestCase):
Verify that 'clean' raises 'ValidationError' if the is_professional_certificate is checked
but no professional_certificate_name has been entered
"""
run_form = CustomCourseRunForm()
run_form = CourseRunForm()
run_form.cleaned_data = {'is_professional_certificate': True, 'professional_certificate_name': ''}
with self.assertRaises(ValidationError):
run_form.clean()
......@@ -187,11 +187,11 @@ class PublisherCourseRunEditFormTests(TestCase):
class PublisherCustomCourseFormTests(TestCase):
"""
Tests for publisher 'CustomCourseForm'
Tests for publisher 'CourseForm'
"""
def setUp(self):
super(PublisherCustomCourseFormTests, self).setUp()
self.course_form = CustomCourseForm()
self.course_form = CourseForm()
self.organization = OrganizationFactory()
self.course = CourseFactory(title='Test', number='a123', organizations=[self.organization])
......@@ -220,7 +220,7 @@ class PublisherCustomCourseFormTests(TestCase):
Verify that clean raises 'ValidationError' if the course title is a duplicate of another course title
within the same organization
"""
course_form = CustomCourseForm()
course_form = CourseForm()
course_form.cleaned_data = {'title': 'Test', 'number': '123a', 'organization': self.organization}
with self.assertRaises(ValidationError):
course_form.clean()
......@@ -233,7 +233,7 @@ class PublisherCustomCourseFormTests(TestCase):
Verify that clean raises 'ValidationError' if the course number is a duplicate of another course number
within the same organization
"""
course_form = CustomCourseForm()
course_form = CourseForm()
course_form.cleaned_data = {'title': 'Test2', 'number': 'a123', 'organization': self.organization}
with self.assertRaises(ValidationError):
course_form.clean()
......@@ -256,7 +256,7 @@ class PublisherCustomCourseFormTests(TestCase):
'organization': organization,
'team_admin': course_admin.id
}
course_form = CustomCourseForm(
course_form = CourseForm(
**{'data': course_from_data, 'instance': course, 'user': course_admin,
'organization': organization}
)
......
......@@ -29,8 +29,8 @@ from course_discovery.apps.publisher import emails, mixins, serializers
from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole
from course_discovery.apps.publisher.dataloader.create_courses import process_course
from course_discovery.apps.publisher.emails import send_email_for_published_course_run_editing
from course_discovery.apps.publisher.forms import (AdminImportCourseForm, CourseSearchForm, CustomCourseForm,
CustomCourseRunForm, CustomSeatForm)
from course_discovery.apps.publisher.forms import (AdminImportCourseForm, CourseForm, CourseRunForm, CourseSearchForm,
SeatForm)
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension, Seat, UserAttributes)
from course_discovery.apps.publisher.utils import (get_internal_users, has_role_for_course, is_internal_user,
......@@ -229,7 +229,7 @@ class CourseRunDetailView(mixins.LoginRequiredMixin, mixins.PublisherPermissionM
class CreateCourseView(mixins.LoginRequiredMixin, mixins.PublisherUserRequiredMixin, CreateView):
""" Create Course View."""
model = Course
course_form = CustomCourseForm
course_form = CourseForm
template_name = 'publisher/add_course_form.html'
success_url = 'publisher:publisher_course_detail'
......@@ -253,7 +253,7 @@ class CreateCourseView(mixins.LoginRequiredMixin, mixins.PublisherUserRequiredMi
ctx = self.get_context_data()
add_new_run = request.POST.get('add_new_run')
# pass selected organization to CustomCourseForm to populate related
# pass selected organization to CourseForm to populate related
# choices into institution admin field
user = self.request.user
organization = self.request.POST.get('organization')
......@@ -328,7 +328,7 @@ class CreateCourseView(mixins.LoginRequiredMixin, mixins.PublisherUserRequiredMi
class CourseEditView(mixins.PublisherPermissionMixin, UpdateView):
""" Course Edit View."""
model = Course
form_class = CustomCourseForm
form_class = CourseForm
permission = OrganizationExtension.EDIT_COURSE
template_name = 'publisher/course_edit_form.html'
success_url = 'publisher:publisher_course_detail'
......@@ -502,8 +502,8 @@ class CourseDetailView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMixi
class CreateCourseRunView(mixins.LoginRequiredMixin, CreateView):
""" Create Course Run View."""
model = CourseRun
run_form = CustomCourseRunForm
seat_form = CustomSeatForm
run_form = CourseRunForm
seat_form = SeatForm
template_name = 'publisher/add_courserun_form.html'
success_url = 'publisher:publisher_course_run_detail'
parent_course = None
......@@ -676,11 +676,11 @@ class CreateRunFromDashboardView(CreateCourseRunView):
class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMixin, UpdateView):
""" Course Run Edit View."""
model = CourseRun
run_form = CustomCourseRunForm
seat_form = CustomSeatForm
run_form = CourseRunForm
seat_form = SeatForm
template_name = 'publisher/course_run/edit_run_form.html'
success_url = 'publisher:publisher_course_run_detail'
form_class = CustomCourseRunForm
form_class = CourseRunForm
permission = OrganizationExtension.EDIT_COURSE_RUN
def get_success_url(self): # pylint: disable=arguments-differ
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-19 01:14-0400\n"
"POT-Creation-Date: 2017-09-20 14:16-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: apps/api/filters.py
#, python-brace-format
......@@ -765,10 +765,6 @@ msgid "Enter Professional Certificate program name"
msgstr ""
#: apps/publisher/forms.py
msgid "Only audit seat can be without price."
msgstr ""
#: apps/publisher/forms.py
msgid "Choose enrollment track"
msgstr ""
......@@ -786,6 +782,10 @@ msgid "Enrollment Track"
msgstr ""
#: apps/publisher/forms.py
msgid "Only audit seat can be without price."
msgstr ""
#: apps/publisher/forms.py
msgid "This field is required."
msgstr ""
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-19 01:14-0400\n"
"POT-Creation-Date: 2017-09-20 14:16-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/api/filters.py
......@@ -906,12 +906,6 @@ msgstr ""
"¢σηѕє¢тєтυя #"
#: apps/publisher/forms.py
msgid "Only audit seat can be without price."
msgstr ""
"Önlý äüdït séät çän ßé wïthöüt prïçé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
#: apps/publisher/forms.py
msgid "Choose enrollment track"
msgstr "Çhöösé énröllmént träçk Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
......@@ -929,6 +923,12 @@ msgid "Enrollment Track"
msgstr "Énröllmént Träçk Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: apps/publisher/forms.py
msgid "Only audit seat can be without price."
msgstr ""
"Önlý äüdït séät çän ßé wïthöüt prïçé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
#: apps/publisher/forms.py
msgid "This field is required."
msgstr "Thïs fïéld ïs réqüïréd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
......
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