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

Add Support for multiples data fields #32

Open
dw-liedji opened this issue Sep 28, 2023 · 2 comments
Open

Add Support for multiples data fields #32

dw-liedji opened this issue Sep 28, 2023 · 2 comments

Comments

@dw-liedji
Copy link

dw-liedji commented Sep 28, 2023

I have used the library and It just works fine with one data field ("mark1" in my case). However It fail for multiples data fields. For examples I would like to display mark1, mark2 and mark3 for each student and for each course. This is my code:

from django.db.models import Sum, F

# Defining the queryset (student_marks) and other parameters

rows = "enrolled_student__student__user__username"
column = "teaching_course__course__name"

# Creating separate aggregation expressions for mark1, mark2, and mark3
data_mark1 = Sum(F('mark1'))
data_mark2 = Sum(F('mark2'))
data_mark3 = Sum(F('mark3'))

# Use the pivot function with multiple data columns
result = pivot(
    queryset=student_marks,
    rows=rows,
    column=column, 
    data={
        'mark1': data_mark1,
        'mark2': data_mark2,
        'mark3': data_mark3,
    },)
@dw-liedji dw-liedji changed the title Support for multiples data fields Add Support for multiples data fields Sep 28, 2023
@martsberger
Copy link
Owner

Can you clarify your data model, does a single student for a single course have multiple values for mark1? I think if you showed the relevant parts of your models, I would better understand.

@dw-liedji
Copy link
Author

Hello @martsberger

Thank you for your quick response.

The model below this text is the part of my database for managing marking for each student and teaching course. I want to report the mark1, mark2, mark3,..., markn of students in a table for every courses. The y axis contains the student name and the x axis contains all the teaching courses.

For each student and each teaching course, the mark1, mark2, mark3,...,markn must be displayed. The marks must be displayed in the subcolumns or dictionary of each teaching course. If a student does not have marks for a teaching course put "N/A" or None.

All the data must be prepared in the backend and the template just for rendering without any conditions. Don't use loops for database queries.

My model

class TeachingCourseStudentMark(BaseModel):
    organization = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name="teaching_course_student_marks",
    )
    teaching_course = models.ForeignKey(
        TeachingCourse,
        on_delete=models.CASCADE,
        related_name="teaching_course_student_marks",
    )
    enrolled_student = models.ForeignKey(
        EnrolledStudent,
        on_delete=models.CASCADE,
        related_name="teaching_course_student_marks",
    )
    mark1 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    mark2 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    mark3 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    mark4 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    mark5 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    mark6 = models.DecimalField(
        max_digits=4, decimal_places=2, null=True, blank=True
    )
    objects = (
        managers.TeachingCourseStudentMarkManager()
    )  # Assign the custom manager

    class Meta:
        unique_together = (
            "organization",
            "teaching_course",
            "enrolled_student",
        )

        constraints = [
            models.CheckConstraint(
                check=models.Q(mark1__gte=0) & models.Q(mark1__lte=100),
                name="check_mark1_range",
            ),
            # Add similar CheckConstraint for other mark fields
            models.CheckConstraint(
                check=models.Q(teaching_course__isnull=False),
                name="check_teaching_course_not_null",
            ),
            models.CheckConstraint(
                check=models.Q(enrolled_student__isnull=False),
                name="check_enrolled_student_not_null",
            ),
            # Add more constraints as needed
        ]

    def __str__(self):
        return f"{self.enrolled_student.student.user.username} - {self.teaching_course.course.name}"

Solution tried

One of the simplest and optimal solution was to use django-pivot. This works fine if I included only one data field (only mark1, or only mark2, ..., or only markn)

This is the implementation that I expect:

from django.db.models import Sum, F

Defining the queryset (student_marks) and other parameters

rows = "enrolled_student__student__user__username"
column = "teaching_course__course__name"

Creating separate aggregation expressions for mark1, mark2, and mark3

data_mark1 = Sum(F('mark1'))
data_mark2 = Sum(F('mark2'))
data_mark3 = Sum(F('mark3'))

Use the pivot function with multiple data columns

result = pivot(
    queryset=student_marks,
    rows=rows,
    column=column, 
    data={
        'mark1': data_mark1,
        'mark2': data_mark2,
        'mark3': data_mark3,
    },)

By adding this feature the library would be more flexible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants