How to compare two queryset to find same and different values and add to calendar
I'm using the HTMLCalendar module provided by Django. In addition to the event, I want to pull the date value from another class to default and display it in the calendar.
First, when the assignment(person) visits the hospital, he enters next_visit. Here, if a patient visits the hospital at an saved next visit, we want to apply a 'text-decoration:line-through' to the next visit data. (get_html_url_drop)
The expression for if n.assignment == c.assignment seems to be correct, but the else case doesn't give me the answer I'm looking for. Please help.
That is, if the assignment is the same by outputting both the next visit and the cycle visit on a specific date, one assignment(next_visit) will be deleted. Strikethrough applies to that person's name because they visited on the scheduled date.
[Leave/models.py]
class Leave(models.Model):
title = models.CharField(max_length=50, blank=True, null=True)
from_date = models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
memo = models.TextField(blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
is_deleted = models.BooleanField(default=False)
create_date = models.DateTimeField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
@property
def get_html_url(self):
url = reverse('leave:leave_edit', args=(self.id,))
return f'<div class="event-title"><a href="{url}" style="color:black;"> {self.title} </a></div>'
[Feedback/models.py]
class Feedback(models.Model):
cycle = models.CharField(max_length=500, default='', blank=True, null=True)
day = models.CharField(max_length=500, default='', blank=True, null=True)
dosing_date = models.DateField(blank=True, null=True)
next_visit = models.DateField(blank=True, null=True)
assignment = models.ForeignKey(Assignment, on_delete=models.SET_NULL, null=True, blank=True)
@property
def get_html_url_next_visit(self):
return f'<div class="next-visit-title"><a href="/assignment/{self.assignment.id}/" style="color:black;">' \
f' {self.assignment.name} {self.assignment.register_number} </a></div>'
@property
def get_html_url_drop(self):
return f'<div class="next-visit-title"><a href="/assignment/{self.assignment.id}/" style="color:black; text-decoration:line-through;">' \
f' {self.assignment.name} {self.assignment.register_number} </a></div>'
@property
def get_html_url_cycle(self):
if self.cycle == 'EOT':
return f'<div class="cycle-title"><a href="/assignment/{self.assignment.id}/" style="color:black;"> ' \
f'{self.assignment.name} {self.assignment.register_number} EOT </a></div>'
else:
return f'<div class="cycle-title"><a href="/assignment/{self.assignment.id}/" style="color:black;"> ' \
f'{self.assignment.name} {self.assignment.register_number} C{self.cycle}D{self.day} </a></div>'
[Leave/utils.py]
from calendar import HTMLCalendar
from .models import Leave
from django.db.models import Q, F
from django.db.models.functions import ExtractMonth
from feedback.models import Feedback
class Calendar(HTMLCalendar):
def __init__(self, year=None, month=None, user=None):
self.year = year
self.month = month
self.user = user
super(Calendar, self).__init__()
# formats a day as a td
# filter events by day
def formatday(self, day, events, next_visit, cycle_visit):
events_per_day = events.filter(user=self.user).annotate(end_date_month=ExtractMonth('end_date'))\
.filter(Q(from_date__day=day, end_date__isnull=True) |
Q(from_date__day__lte=day, end_date__day__gte=day) |
(Q(from_date__day__lte=day, from_date__year=self.year, from_date__month=self.month) &
~Q(from_date__month=F('end_date_month'))) |
(Q(end_date__day__gte=day, end_date__year=self.year, end_date__month=self.month) &
~Q(from_date__month=F('end_date_month'))))
next_visit_per_day = next_visit.filter(next_visit__day=day, next_visit__year=self.year, next_visit__month=self.month, assignment__curr_crc=self.user.first_name)
cycle_per_day = cycle_visit.filter(dosing_date__day=day, dosing_date__year=self.year, dosing_date__month=self.month, assignment__curr_crc=self.user.first_name)\
d = ''
for event in events_per_day:
d += f'{event.get_html_url}'
for n, c in zip(next_visit_per_day, cycle_per_day):
if n.assignment == c.assignment:
d += f'{cycle_visit.get_html_url_cycle}'
else: ----> I think this part needs to be fixed.
d += f'{cycle_visit.get_html_url_next_visit}'
for cycle_visit in cycle_per_day:
d += f'{cycle_visit.get_html_url_cycle}'
if day != 0:
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
return '<td></td>'
# formats a week as a tr
def formatweek(self, theweek, events, next_visit, cycle_visit):
week = ''
for d, weekday in theweek:
week += self.formatday(d, events, next_visit, cycle_visit)
return f'<tr> {week} </tr>'
# formats a month as a table
# filter events by year and month
def formatmonth(self, withyear=True):
events = Leave.objects.filter(is_deleted=False)\
.filter(Q(from_date__year=self.year, from_date__month=self.month) |
Q(end_date__year=self.year, end_date__month=self.month))
next_visit = Feedback.objects.filter(assignment__is_deleted=0, next_visit__isnull=False)
cycle_visit = Feedback.objects.filter(assignment__is_deleted=0, cycle__isnull=False, dosing_date__isnull=False)
cal = f'<table border="0" cellpadding="0" cellspacing="0" class="calendar">\n'
cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
cal += f'{self.formatweekheader()}\n'
for week in self.monthdays2calendar(self.year, self.month):
cal += f'{self.formatweek(week, events, next_visit, cycle_visit)}\n'
return cal