Django: in views how can a redirect if the paramater(linked to a url pattern) does not match a model result?

I apologize am still learning django and am just hitting my head on a wall with some of it. The current issue is that I have a view linked through a URL parameter the issue and it works for showing my model info but if you hard type the url to a different parameter it shows the page. I have tried to redirect it but that is not working I feel like it might because of how and where I return my render. Any advice on how to set up url's base off model and if that model info doesn't exist either through a 404 or redirect to a different page?

View:

@login_required(login_url='login_register')
def project_page(request, name):
  project = Project.objects.all()
  issueticket1 = Issue.objects.filter(related_project__name__exact=name)
  table = IssueTable(issueticket1)
  project_list = {}
  for p in project:
      if p.name == name:
          project_list = {'id': p.project_id, 'startdate': p.start_date,
                          'enddate': p.end_date, 'description': p.description}
return render(request, 'main_projects.html', {'name': name, 'project_list': project_list, 'project': project, 'table': table})

URL CONFIG:

path('projects/<str:name>/', views.project_page, name="project_page"),

Don't know what your exact goal is, it's not very clear to me so I'm guessing here. But the best thing to do when an object doesn't exist when getting an object is to return a 404 not found error message.

So in your code you're basically getting all projects and using if statements to check if they match the name. Which can be quite expensive for the database and aside that looping through all the projects is not advisable, imagine you had 1000 projects in your database it means you're going through each one of them and checking if the name matches that will prevent the page from loading quickly.

What you can do instead is to use the filter method, and retrieve all projects matching the name.

from django.shortcuts import get_object_or_404, redirect
from django.core.exceptions import ValidationError


@login_required(login_url='login_register')
def project_page(request, name):
    project_list = Project.objects.all()
    issueticket1 = Issue.objects.filter(related_project__name__exact=name)
    table = IssueTable(issueticket1)

    # Instead of looping get the projects get the matching item, you can use get_object_or_404 from django
    project = get_object_or_404(Project, name=name)
    # or an alternative 
    try:
        project = project_list.get(name=name)
    except Project.DoesNotExist:
        raise ValidationError("project does not exist")
        # If you really need to redirect you can
        return redirect("/your-url/")

    return render(request, 'main_projects.html', {'name': name, 'project_list': project_list, 'project': project, 'table': table})

You could just add an if statement inside your template

{% if issueticket1 %}
  ~Do the Normal things~
{% else %}
  No Match Was Found
{% end if %}

you could also do the 404 thing like @kwamito said, that's always good.

Or you could just add and if in the view and a custom redirect like:

  • I'm not sure 100% on how this is supposed to work, so just gonna throw two potential redirects in there
@login_required(login_url='login_register')
def project_page(request, name):

  projectMatches = Project.objects.filter(name=name)
  if not projectMatches.count():
    # No Projects
    redirect('errorpage')

  # Note: .first() - it will be the Object or None
  issueticket1 = Issue.objects.filter(related_project__name__exact=name).first()
  if not issueticket1:
    # No Tickets
    redirect('errorpage')

  table = IssueTable(issueticket1)
  project_list = {}

  for p in projectMatches:
    project_list = {'id': p.project_id, 'startdate': p.start_date,
                    'enddate': p.end_date, 'description': p.description}
  return render(request, 'main_projects.html', {'name': name, 'project_list': project_list, 'project': project, 'table': table})

Eitherway you should probably use Project.objects.filter() instead of looping through all of them and manually checking names (make the db do that)

Back to Top