Django中双Slug URL路径实现是否合理?有无更优方案?
Hey there! Let's break down your current implementation and share some optimizations to make it cleaner, more efficient, and safer.
Current Implementation Issues
Looking at your code, there are a few areas we can improve:
- Redundant Database Queries: You first fetch
lolmatchwithget_object_or_404, then run anotherfilteronLeagueOfLegendsGameto getgame[0]—this is unnecessary since you already have the full object inlolmatch. - Potential Error Risk: Using
game[0]after afiltercould throw anIndexErrorif the slug doesn't exist (even thoughget_object_or_404should catch it, it's still a fragile pattern). - Weak Validation: Right now, you're checking if a tournament with the given slug exists and is linked to the game, but you aren't explicitly verifying that the specific match (lolslug) actually belongs to the tournament in the URL. A user could manually swap the tournament slug in the URL and still access the match if the tournament is linked to any game, not necessarily this one.
Optimized Solution
Here's how to fix these issues while keeping your desired URL structure:
1. Refactor the View
We'll eliminate redundant queries and add proper validation to ensure the match belongs to the specified tournament:
# views.py def lolmatch_detail(request, tournamentslug, lolslug): # Fetch the match AND ensure it belongs to the tournament in the URL lolmatch = get_object_or_404( LeagueOfLegendsGame, lol_slug=lolslug, tournament__tournament_slug=tournamentslug ) # No need for extra queries—lolmatch already has the tournament relation tournament = lolmatch.tournament # Rest of your view logic here...
This single get_object_or_404 call does two things:
- Finds the match with the given
lolslug - Ensures that match is associated with the tournament specified by
tournamentslug
If either condition fails, it returns a 404, which is exactly what we want.
2. Verify Model Relationships
Your current model setup looks okay, but just to confirm: since LeagueOfLegendsGame has a ForeignKey to Tournament, each match is tied to one tournament. This aligns perfectly with your URL structure (a match lives under one tournament).
3. Keep the URLconf as-Is
Your existing URL path is already correct for your desired structure—no changes needed here:
# urls.py path('lol/tournament/<str:tournamentslug>/match/<str:lolslug>', lolmatch_detail, name='lol_match_detail'),
Why This Is Better
- Fewer Queries: We've reduced the number of database hits from 3 to 1, which improves performance.
- Safer: Users can't access a match under the wrong tournament slug—they'll get a 404 if they try to manipulate the URL.
- Cleaner Code: The view is more concise and easier to maintain.
内容的提问来源于stack exchange,提问作者Enes

