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

Created models for penn wrapped -- issue with pip files though #309

Merged
merged 11 commits into from
Nov 17, 2024

Conversation

zachHarpaz
Copy link
Contributor

No description provided.

@tuneerroy tuneerroy marked this pull request as draft September 29, 2024 18:13
zachHarpaz and others added 3 commits October 13, 2024 12:53
request should look like this format:

/wrapped/generate/?username=zharpaz&semester=2020A
Copy link
Contributor

@vcai122 vcai122 left a comment

Choose a reason for hiding this comment

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

Good work so far! Django has a lot of intricacies but you're doing a good job navigating them so keep up the good work. Let me know if you have any questions about comments



class GlobalStat(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.

You don't need to prefix with stat_ because it's a bit redundant



# Add a new model for keys
class UserStatKey(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 keep the names consistent and call this IndividualStatKey


# Add a new model for keys
class UserStatKey(models.Model):
stat_key = models.CharField(max_length=50, null=False, blank=False)
Copy link
Contributor

Choose a reason for hiding this comment

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

same here about stat_ prefix. Also make this the primary key

# How to do this, using individual vs stat_key ?
name = models.CharField(max_length=50, null=False, blank=False)
template_path = models.CharField(max_length=50, null=False, blank=False)
stat_locations = models.ManyToManyField(StatLocation, blank=True)
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 this a through model see Gsr Group to User through GroupMembership as an example.

Also let's not make this "one or the other" model. Let's just make the administrator specify whether it would be individual or global through 2 seperate many to manys. It seems reasonable for the administrator to think about this anyway.

class Page(models.Model):

# How to do this, using individual vs stat_key ?
name = models.CharField(max_length=50, null=False, blank=False)
Copy link
Contributor

Choose a reason for hiding this comment

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

This name should be for internal use only. Also make it a primary key to ensure uniqueness.

User = get_user_model()


class GeneratePage(viewsets.ModelViewSet):
Copy link
Contributor

Choose a reason for hiding this comment

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

get the user through request.user, and make sure you have to be authenticated to use this route. see our other views.

Also I don't think ModelViewSet is the right viewset to use here.

Also call this and associated urls Pages. We're not really generating anything (generating implies side effects). We're just serializing data already in the db: we are returning Pages filtered for the given semester, serialized in a particular way.

Copy link
Contributor

@vcai122 vcai122 Oct 20, 2024

Choose a reason for hiding this comment

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

Actually now that we are adding a Semester model, this should be thought of as returning data associated with 1 particular semester.

(And in the serializer for semester it turns it into a list of pages each of which can be serialized with the page serializer and so on...)

EDIT: actually I'm not partial to either, I think thinking about it as returning a list of pages seems fine too.

pages = Page.objects.filter(semester=semester)

# Serialize the data
serializer = PageSerializer(pages, many=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

what does the many=True here do

@@ -0,0 +1,76 @@
from django.db import models
Copy link
Contributor

Choose a reason for hiding this comment

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

I know we talked about this before but I think we should actually make Semester a model again.
Reason I'm saying this is for admin page purposes, we can use inline models to manage all the pages for a particular semester at a time which seems like a clean way to do it.

We would make a semester model with 1 field, and make it many to many on pages.

We should think of a Page from now on as a page reusable across semesters

Copy link
Contributor

Choose a reason for hiding this comment

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

Leaving this here because we should probably use this later: https://django-admin-sortable2.readthedocs.io/en/latest/

Copy link
Contributor

Choose a reason for hiding this comment

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

So you have to also make GlobalStatKey model

model = UserStatKey
fields = ["stat_key"]

class PageSerializer(serializers.ModelSerializer):
Copy link
Contributor

Choose a reason for hiding this comment

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

You're not really using the other serializers since you're just serializing it and immediately reformatting it, so might as well not use it.

The way you should be thinking about serializers is that everytime you have a queryset and then you say to yourself "I wish I could have this queryset in this particular format" you should make a serializer.

Finished Models for wrapped and serializer working
Copy link
Contributor

@vcai122 vcai122 left a comment

Choose a reason for hiding this comment

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

Looking very promising! Next steps would be to clean up a lot of the dead code and get it ready to merge.

Most comments I left should be pretty quick and so let's just get this into a ready to merge state soon.



# Why do we want time? Ask Vincent
class Page(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.

lets move this to the bottom so we don't have to specify the many to many models using strings



# Why do we want time? Ask Vincent
class Page(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.

also we need a duration field indicating how long this page should stay on screen for. This would be allowed to be empty



class IndividualStatThrough(models.Model):
IndividualStatKey = models.ForeignKey(IndividualStatKey,null=False, blank=False, default=None ,on_delete=models.CASCADE)
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason this is IndividualStatKey instead of individual_stat_key? same with others below





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 call this something more descriptive to its actual inherent meaning. Maybe IndividualStatPageField (and the other GlobalStatPageField

from .models import Page, Semester
from .serializers import PageSerializer
from .serializers import SemesterSerializer

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that your doing it the django way, you can get away with writing even less code :)
e.g. something like this

class MyModelViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

Copy link
Contributor

Choose a reason for hiding this comment

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

Note you don't need to pass in user in context. See how we access the user in serializers in our other code (e.g. Portal serializer)

model = Semester
fields = ['semester', 'pages']

def get_pages(self, obj):
Copy link
Contributor

Choose a reason for hiding this comment

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

You are manually writing what django can already do if you just hook up pages directly with the serializer. (See sublet serializers for example).
e.g.

    amenities = serializers.PrimaryKeyRelatedField(
        many=True, queryset=Amenity.objects.all(), required=False
    )
    images = SubletImageURLSerializer(many=True, required=False)

Copy link
Contributor

Choose a reason for hiding this comment

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

wait sorry i think for this you need to manually pass the semester obj so yours is correct. But its kinda verbose why not just:

return PageSerializer(obj.pages.all(), many=True, context={'semester': obj}).data

from .models import Page, IndividualStat, GlobalStat, IndividualStatThrough, GlobalStatThrough, Semester, User

class IndividualStatSerializer(serializers.ModelSerializer):
key = serializers.StringRelatedField()
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 not use StringRelatedField because it relies on the __str__ which is ususally used for testing. Can you find a better one to use?

user = self.context.get('user')
semester = self.context.get('semester')

individual_throughs = IndividualStatThrough.objects.filter(Page=obj)
Copy link
Contributor

Choose a reason for hiding this comment

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

You a bit too much manual serialization here. As an outline the following is a bit more reasonable:

  1. Serialize IndividualEntries to become a list of (field_name, value) pairs (using a serializer)
    2.Serialize IndividualEntries to become a list of (field_name, value) pairs (using a serializer)
  2. Combine into a dict and return.

Although this seems hard to describe over a code review. Maybe we can sit down and peer program for this part

user = self.context.get('user')
semester = self.context.get('semester')

try:
Copy link
Contributor

Choose a reason for hiding this comment

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

prefer filter(...).first() over get()

Copy link

codecov bot commented Nov 15, 2024

Codecov Report

Attention: Patch coverage is 82.57576% with 23 lines in your changes missing coverage. Please review.

Project coverage is 90.23%. Comparing base (8315c52) to head (5408760).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
backend/wrapped/serializers.py 68.42% 12 Missing ⚠️
backend/wrapped/models.py 86.20% 8 Missing ⚠️
backend/wrapped/views.py 72.72% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #309      +/-   ##
==========================================
- Coverage   90.59%   90.23%   -0.36%     
==========================================
  Files          61       66       +5     
  Lines        2552     2684     +132     
==========================================
+ Hits         2312     2422     +110     
- Misses        240      262      +22     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@vcai122 vcai122 left a comment

Choose a reason for hiding this comment

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

LGTM!
Notes before merging:

  • Merge in master to get rid of build errors
  • Make sure everything is passing (except for test coverage)
  • Note down the decrease in code coverage, you'll be responsible for bringing it up in ur next PR

@zachHarpaz zachHarpaz marked this pull request as ready for review November 17, 2024 17:45
@zachHarpaz zachHarpaz merged commit d1044c2 into master Nov 17, 2024
7 of 9 checks passed
@zachHarpaz zachHarpaz deleted the penn-wrapped branch November 17, 2024 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants