Query data linked via Foreign key

I have 2 models linked 'Project' and 'Event'. Event has an FK to Project

I want to return all events that are related only to the project.

I have a basic view that returns the specific project and im trying to include the event list within that view.

def show_project_details(request,project_id):
    today = now().date()
    project = Project.objects.get(pk=project_id)
    events = Event.objects.event_list = Event.objects.filter(event_date__gte=today).order_by('event_date')
    events_list = Event.objects.get(project_name_id=project_id)
    form = ProjectForm(request.POST or None, instance=project)

    return render(request, 'pages/project_details.html', {"project": project, "form": form, "events": events, 'events_list':events_list})

but it returns

Event matching query does not exist.

Any ideas?

to get all the event related to a particular project use

project = Project.objects.get(pk=project_id)
events = project.event_set.filter(event_date__gte=today).order_by('event_date')

so the full view would reduce to

def show_project_details(request,project_id):
    today = now().date()
    project = Project.objects.get(pk=project_id)
    events = project.event_set.filter(event_date__gte=today).order_by('event_date')
    form = ProjectForm(request.POST or None, instance=project)

    return render(request, 'pages/project_details.html', {"project": project, "form": form, "events": events})

Brian Obot's answer is a very good solution to your actual problem.


To answer your question why you get this specific error with your code:

Event matching query does not exist.

As you have not (yet) provided your models, I can only guess that the error occurs for this line of code:

events_list = Event.objects.get(project_name_id=project_id)

objects.get will always raise an error if it does not exactly find 1 single object. For fetching data that can return 0 to many results (as is the case for regular reverse foreign key relations), you should use filter.

Your current code should work if you change the above line to:

events_list = Event.objects.filter(project_name_id=project_id)

This really will return a list (actually a queryset) - that could also be empty.


In terms of performance / amounts of statements executed on the database:

Both ways (project.event_set and Event.objects.filter) will result in extra statements to the database.

If you want to avoid that and fetch everything when you fetch the project data, you would have to work with annotations.

As long as you are not experiencing any issues, it's fine to leave it as is. If you are interested to venture into that area, read more: https://docs.djangoproject.com/en/3.2/ref/models/querysets/#annotate

Back to Top