Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add platform model and associated fields in Course and Program models #2699

Merged
merged 16 commits into from
Aug 31, 2023

Conversation

asadali145
Copy link
Contributor

@asadali145 asadali145 commented Aug 8, 2023

Pre-Flight checklist

  • Migrations
    • Migration is backwards-compatible with current production code
  • Testing
    • Code is tested
    • Changes have been manually tested

What are the relevant tickets?

Fixes #2698

What's this PR do?

Adds a new model named Platform for course/program partners. Also, adds foreign key fields in the Course and Program models.

How should this be manually tested?

  • Visit Django admin and verify that Platforms is listed.
  • Add/Edit any course/program and verify that the platform field is visible.
  • Verify that platform field is added in the APIs

Copy link
Contributor

@arslanashraf7 arslanashraf7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also think ahead of time while adding this.

There are two things that are coming to my mind right now:

  1. Let's confirm if this is something we want the course team to manage in which case we might need to allow Partner model manipulation and association through Wagtail/CMS. Just like how we manage topics Django model through CMS. This will allow the course team to manage partners through Wagtail without involving the engineering team.
  2. Some time ago we added a partner logo in certificates at Partner logo in certificate template #2407. This is time we should think if we want to move that to this partner model.

What are your thoughts on this. @pdpinch @cachob

@@ -209,6 +209,17 @@ def catalog_image_url(self):
)


class Partner(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's inherit this from TimestampedModel

@cachob
Copy link

cachob commented Aug 15, 2023

  1. Let's confirm if this is something we want the course team to manage in which case we might need to allow Partner model manipulation and association through Wagtail/CMS. Just like how we manage topics Django model through CMS. This will allow the course team to manage partners through Wagtail without involving the engineering team.

I suggest that we keep the control in Django, and not on the CMS. This is a setting that should rarely be touched since we do not get a lot of new external partners.

  1. Some time ago we added a partner logo in certificates at Partner logo in certificate template #2407. This is time we should think if we want to move that to this partner model.

Marketing does not want branding on the course catalog of the xPRO site. So we won't be needing this at least at the moment. Is this a complex thing to add?

@arslanashraf7
Copy link
Contributor

Marketing does not want branding on the course catalog of the xPRO site. So we won't be needing this at least at the moment. Is this a complex thing to add?

@cachob I think we can migrate the existing partners' logs if/when needed. In my opinion that should not be very hard, What I can think of right now is: (When we will need to associate partners with Logo)

  1. Create a model in Wagtail e.g. PartnerLogo Having a foreign key from the Partner Django model and and Image field.
  2. Allow CertificatePage to have a foreign key of PartnerLogo instead of the image field that it currently has
  3. Refactor the code around certificates to use this model
  4. Properly migrate exiting partner logos from certificate page.

Copy link
Contributor

@arslanashraf7 arslanashraf7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of minor changes suggested.
I haven't tested it yet. I'll test it in the final review. Thanks for your patience on this.

Model for course partner
"""

name = models.CharField(max_length=255)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it unique(case-insensitive), I don't think we might need to ever support partners with the same name.

courses/admin.py Outdated
@@ -377,6 +375,14 @@ class CourseTopicAdmin(ModelAdmin, admin.ModelAdmin):
delete_view_class = TopicsWagtailDeleteView


class PartnerAdmin(admin.ModelAdmin):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should inherit from TimestampedModelAdmin to reuse its display properties, I could not see date fields on the partner detail page in Django Admin.
image

class PartnerFactory(DjangoModelFactory):
"""Factory for Company"""

name = factory.Faker("partner")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we make the partner name unique, This will also be changed to have a prepending dynamic/random name.

@@ -220,6 +231,9 @@ class Program(TimestampedModel, PageProperties, ValidateOnSaveMixin):
live = models.BooleanField(default=False)
products = GenericRelation(Product, related_query_name="programs")
is_external = models.BooleanField(default=False)
partner = models.ForeignKey(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, We should have had a common model e.g. Courseware having all the common fields from Course, Program models e.g. live, title, readable_id. And the Course, Program models would inherit from that. Let me know what you think. Maybe we can keep this here for now and do a full refactor of all these in another PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should do this in a separate PR.

@@ -187,6 +188,10 @@ def get_format(self, instance): # pylint: disable=unused-argument
# configurable.
return "Online"

def get_partner(self, instance):
"""Returns the partner of the course"""
return instance.partner.name if instance.partner else None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
return instance.partner.name if instance.partner else None
return getattr(instance.partner, "name", None)

@@ -187,6 +188,10 @@ def get_format(self, instance): # pylint: disable=unused-argument
# configurable.
return "Online"

def get_partner(self, instance):
"""Returns the partner of the course"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Returns the partner of the course"""
"""Returns the partner name of the course"""

Validates case insensitive partner name uniqueness.
"""
if (
self._state.adding
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be enabled for editing mode, Because you can still produce case insensitive partners by in edit mode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, This doesn't work through the shell. I tried and I could create multiple partners with the same name.

image

courses/models.py Show resolved Hide resolved
Copy link
Contributor

@arslanashraf7 arslanashraf7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Looks good. Thanks for your patience on this.

with pytest.raises(ValidationError):
PartnerFactory.create(name="emeritus")

PartnerFactory.create(name="Emirates")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This line/creation might not be needed. I think the above assertion is enough.

@pdpinch
Copy link
Member

pdpinch commented Aug 29, 2023

Please hold off on merging this. I want to review the field name and make sure it's aligned with field names in MIT Open.


operations = [
migrations.CreateModel(
name="Partner",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with MIT Open, can we call this "Platform" instead of "Partner"

Sorry I didn't bring this up earlier.

@asadali145 asadali145 changed the title feat: Add partner model and associated fields in Course and Program models feat: Add platform model and associated fields in Course and Program models Aug 30, 2023
@asadali145
Copy link
Contributor Author

@pdpinch Could you please have a look into this PR now?

@asadali145 asadali145 merged commit 51ac860 into master Aug 31, 2023
3 checks passed
@odlbot odlbot mentioned this pull request Aug 31, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add platform model association with Courses and Programs
5 participants