Search code examples
djangourlviewdjango-templatesmodel

get_absolute_url is NOT working on the combined queryset, How can l do it?


I want to use get_absolute_url but it shows nothing on the combined queryset

It returns an error that: Page not found Below are my codes

#Action/models.py

class Action(models.Model): 
......
def get_absolute_url(self):
   return reverse('act',args=[self.slug])






#adventure/models.py


class Adventure(models.Model): 

......

def get_absolute_url(self):

   return reverse('adves',args=[self.slug])







#racing/models.py

class Racing(models.Model): 
......
def get_absolute_url(self):
   return reverse('act',args=[self.slug])





#puzzle/models.py

class Puzzle(models.Model): 
......
def get_absolute_url(self):
   return reverse('puz',args=[self.slug])

Then view of my combined queryset

#Others/views.py
from itertools import chain
def games(request):
...  .....

 act_games=Action.objects.all()
 adv_games=Adventure.objects.all()
 puz_games=Puzzle.objects.all()
 rac_games=Racing.objects.all()

 games=  list(chain(act_games,adv_games,puz_games,rac_games))
 context={
 'games':games,
}
 return render(request,'combined.html', context)

#combined.html
.......

{% for game in games %}
<div class="col">
<a href="{{ game.get_absolute_url }}"> {{ game.game_name }} </a>
{% endfor %}

.....

My Expections

When I refleshed the page l found no error. But when I tried clicking on the link,

It returned an error that

Page not found

Now l would like to know how make it pass successfully and take me to the slug link added when creating the object. E.g

When clicking on the action game on the combined page when it was created in the Action models it must redirect me to the slug link page but just returns me 404 Page not found

Someone requested for the Urls so I decided to add these part too

#Action/views.py
from django.shortcuts import render, get_object_or_404

def act(request, description):
 description=get_object_or_404(Action, slug=description)
 Context={'description': description}
 return render(request, 'description.html', Context)


#action/url.py

path('action', views.action, name='action'),
path('description/<slug:description>/', views.act, name='act' )

#Adventure/views.py
from django.shortcuts import render, get_object_or_404

def adv(request, description):
 description=get_object_or_404(Adventure, slug=description)
 Context={'description': description}
 return render(request, 'description.html', Context)


#adventure/url.py

path('adventure', views.adventure, name='adventure'),
path('description/<slug:description>/', views.adv, name='adv' )

#puzzle/views.py
from django.shortcuts import render, get_object_or_404

def puz(request, description):
 description=get_object_or_404(Puzzle, slug=description)
 Context={'description': description}
 return render(request, 'description.html', Context)


#puzzle/url.py

path('puzzle', views.puzzle, name='puzzle'),
path('description/<slug:description>/', views.puz, name='puz')
 

#Racing/views.py
from django.shortcuts import render, get_object_or_404

def rac(request, description):
 description=get_object_or_404(Action, slug=description)
 Context={'description': description}
 return render(request, 'description.html', Context)


#Racing/url.py

path('racing', views.racing, name='racing'),
path('description/<slug:description>/', views.rac, name='rac') 

That is it , seek ur help please


Solution

  • Your paths are overlapping. Indeed, for adventures and puzzles, the URLs are:

    path('adventure', views.adventure, name='adventure'),
    path('description/<slug:description>/', views.adv, name='adv')
    path('puzzle', views.puzzle, name='puzzle'),
    path('description/<slug:description>/', views.puz, name='puz')

    so imagine that the URL is description/adv-slug, then which path should Django take? It will always take the first one, so in this case adv, even if there is no such slug. As a result a lot of URLs, generated for puzzles, will not work.

    Even if that would work, if an Adventure and Puzzle object would somehow have the same slug, then another problem would arise: that both paths are valid.

    You therefore better make non-overlapping URLs, like:

    # adventure/url.py
    
    path('adventure', views.adventure, name='adventure'),
    path('adventure/<slug:description>/', views.adv, name='adv')
    
    # puzzle/url.py
    
    path('puzzle', views.puzzle, name='puzzle'),
    path('puzzle/<slug:description>/', views.puz, name='puz')

    You should also update your Racing model:

    class Racing(models.Model):
        # …
        def get_absolute_url(self):
            return reverse('rac', args=[self.slug])