Home > OS >  Dynamic Django urls redirects to the wrong function
Dynamic Django urls redirects to the wrong function

Time:02-17

So what I am trying to do is create urls such that the user can see complaints either by passing a particular parameter or sort by upvotes by default if no parameter is passed.

urls.py

path('', views.exploreComplaints, name='explore-complaints'),
path('?sort_by=<str:sorting_parameter>/', views.exploreComplaints, name='explore-complaints-by-parameter'),

views.py

def exploreComplaints(request, sorting_parameter="upvotes"):
    complaints = Complaint.objects.all()
    if(sorting_parameter=="name"):
        complaints = sorted(complaints, key = lambda x : x.complaint_name)
    else:
        complaints = sorted(complaints, key = lambda x : x.complaint_upvotes, reverse = True)
    context = {'complaints':complaints}
    return render(request, 'complaints/complaints.html', context)

The sorting parameter does not work when I go to a URL, the value of sorting_parameter is always upvotes, even when I go to a url with ?/sort_by=name in the end. Where am I wrong?

Edit: Complaint Model:

class Complaint(models.Model):
    complaint_title =                   models.CharField(max_length = 1000, null = True)
    complaint_filer =                   models.ForeignKey(User, null = True, on_delete = models.CASCADE)
    complaint_description =             models.TextField(null = True)
    complaint_status =                  models.CharField(max_length = 10, default = 'active')
    complaint_request_image =           models.ImageField(null = True, blank = True, upload_to = 'complaints', default = 'complaints/default-image.jpg')
    complaint_place =                   models.CharField(max_length = 1000, null = True)
    complaint_under_investigation_by =  models.CharField(max_length = 1000, null = True, blank = True)
    complaint_upvotes =                 models.IntegerField(default = 0)
    complaint_upvotes_users =           models.TextField(default=',', blank = True)
    complaint_downvotes_users =         models.TextField(default=',', blank = True)
    tags = TaggableManager()

    def __str__(self):
        return self.complaint_title

CodePudding user response:

Django URL dispatcher doesn't look at GET or POST parameters while resolving the handler.

What you need is to access request.GET mapping in the view: Django request get parameters

In your case, the view definition would look like:

urls.py

urlpatterns = [
    path('', views.exploreComplaints, name='explore-complaints'),
]

views.py

def exploreComplaints(request):
    complaints = Complaint.objects.all()
    sorting_parameter = request.GET.get("sort_by")
    if sorting_parameter == "name":
        complaints = sorted(complaints, key=lambda x: x.complaint_name)
    else:
        complaints = sorted(complaints, key=lambda x: x.complaint_upvotes, reverse=True)
    context = {'complaints':complaints}
    return render(request, 'complaints/complaints.html', context)


# or, to offload sorting on the database:

def explore_complaints(request):
    # distinguish the model field to sort by
    sorting_parameter = request.GET.get("sort_by")
    ordering_param = "-complaint_upvotes"  # default ordering

    if sorting_parameter == "name":
        ordering_param = "complaint_name"

    # add ORDER BY clause to the final query
    complaints = Complaint.objects.order_by(ordering_param)

    context = {"complaints": complaints}
    return render(request, "complaints/complaints.html", context)
  • Related