Django.fun

Restrict view on utils.py - Django

I've used a tempalte to create a calendar using Django, but now i'm stuck to limit the view of the events on this calendar to just the user who have created the event.

I have no model for this calendar, just for the events, and the calendar is currently based on my util.py file:

utils.py

class Calendar(HTMLCalendar):
    def __init__(self, year=None, month=None):
        self.year = year
        self.month = month
        super(Calendar, self).__init__()

    # formats a day as a td
    # filter events by day
    def formatday(self, day, events):
        contracts_starting_per_day = events.filter(starting_date__day=day)
        contracts_ending_per_day = events.filter(ending_date__day=day)
        contracts_paying_per_day = events.filter(payment_date__day=day)
        d = ''


        for contract in contracts_starting_per_day:
            if contract.company_client:
                client = contract.company_client
            elif contract.person_client:
                client = contract.person_client
            else:
                client = '-'
            d += f"<a href='http://127.0.0.1:8000/contracts/editct/{contract.id}'> <li class='calendar-li starting' title='{contract.contract_name}'> {contract.contract_name} <p class='calendar-p'> {client} </p> </li> </a>"


        if day != 0:
            return f"<td class='calendar-td'><span class='date'>{day}</span><ul class='calendar-ul'> {d} </ul></td>"
        return "<td class='calendar-td'></td>"

    # formats a week as a tr
    def formatweek(self, theweek, events):
        week = ''
        for d, weekday in theweek:
            week += self.formatday(d, events)
        return f"<tr class='calendar-tr'> {week} </tr>"

    # formats a month as a table
    # filter events by year and month
    def formatmonth(self, withyear=True):
        contracts = Contract.objects.filter(starting_date__year=self.year, starting_date__month=self.month)

        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, contracts)}\n'
        return cal

views.py

class CalendarView(LoginRequiredMixin, generic.ListView):
    model = Contract
    template_name = 'calendar.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Get the actual month to display the calendar
        d = get_date(self.request.GET.get('month', None))
        agenda = Calendar(d.year, d.month)
        html_agenda = agenda.formatmonth(withyear=True)
        #context['calendar'] = context['calendar'].filter(user=self.request.user)
        context['calendar'] = mark_safe(html_agenda)
        context['prev_month'] = prev_month(d)
        context['next_month'] = next_month(d)
        return context


def get_date(req_day):
    if req_day:
        year, month = (int(x) for x in req_day.split('-'))
        return date(year, month, day=1)
    return datetime.today()


def prev_month(d):
    first = d.replace(day=1)
    prev_month = first - timedelta(days=1)
    month = 'month=' + str(prev_month.year) + '-' + str(prev_month.month)
    return month

def next_month(d):
    days_in_month = calendar.monthrange(d.year, d.month)[1]
    last = d.replace(day=days_in_month)
    next_month = last + timedelta(days=1)
    month = 'month=' + str(next_month.year) + '-' + str(next_month.month)
    return month

I've tried #context['calendar'] = context['calendar'].filter(user=self.request.user) on my views, but i went trough this error:

KeyError at /agenda/calendar 'calendar'

Is there any option to restric the events on the calendar only if the user logged and the user who created the events are equal?

I've also tryed to:

for contract in contracts_starting_per_day:
    if contract.user == request.user:

On my Calendar util, but since this util does not receive any request, it's not possible to use it.

You are trying to retrieve calendar from context while it is not yet in the context. Error is caused in this line:

context['calendar'] = context['calendar'].filter(user=self.request.user)

You should define the queryset for your model in get_queryset method of View. That queryset will be accessible in context in variable you set in context_object_name:

class CalendarView(...):
    ...
    context_object_name = 'contracts'
    def get_queryset(self):
        return Contract.objects.filter(user=self.request.user)

Then in template:

{% for contract in contracts %}
    {{ contract }}
{% endfor %}

Tutorials

Современный Python: начинаем проект с pyenv и poetry

Настройка проекта Python — виртуальные среды и управление пакетами

Использование requests в Python — тайм-ауты, повторы, хуки

Понимание декораторов в Python

ProcessPoolExecutor в Python: полное руководство

map() против submit() с ProcessPoolExecutor в Python

Понимание атрибутов, словарей и слотов в Python

Полное руководство по slice в Python

Выпуск Django 4.0

Безопасное развертывание приложения Django с помощью Gunicorn, Nginx и HTTPS

Автоматический повтор невыполненных задач Celery

Django REST Framework и Elasticsearch

Докеризация Django с помощью Postgres, Gunicorn и Nginx

Асинхронные задачи с Django и Celery

Релизы безопасности Django: 3.2.4, 3.1.12 и 2.2.24

Выпуски исправлений ошибок Django: 3.2.3, 3.1.11 и 2.2.23

Эффективное использование сериализаторов Django REST Framework

Выпуски безопасности Django: 3.2.2, 3.1.10 и 2.2.22

Выпущенные релизы безопасности Django: 3.2.1, 3.1.9 и 2.2.21

Обработка периодических задач в Django с помощью Celery и Docker

View all tutorials →