0

I'm trying to include an template and utilize it in two different views, where the first one gets one url param and the second gets the same plus another one. Inside my included template there is an iteration with a {% url %} tag that I need to pass both params, since the second view needs them, but doing this causes NoReverseMatch when trying to render my first view, probably because it only accepts one param. Is there any way to specifying the second param is optional?

Here is my code:

urls.py

...

    url(r'^portfolio/(?P<category_slug>[-\w]+)/$', views.category, name='category'),
    url(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<album_slug>[-\w]+)/$', views.album, name='album'),

...

models.py

...

class Album(models.Model):
    cover = models.ImageField()
    title = models.CharField(max_length=200, unique=True)
    description = models.CharField(max_length=200, blank=True)
    posts = models.ManyToManyField(Post, blank=True)
    slug = models.SlugField(max_length=200)


class Category(models.Model):
    cover = models.ImageField()
    title = models.CharField(max_length=200, unique=True)
    albums = models.ManyToManyField(Album, blank=True)
    slug = models.SlugField(max_length=200)


@receiver(pre_save, sender=Album)
@receiver(pre_save, sender=Category)
def save_slug(sender, instance, *args, **kwargs):
    instance.slug = slugify(instance.title)

...

views.py

    ...

    def index(request):
        main_categories = Category.objects.filter(...)
        return render(request, 'index.html', {'main_categories': main_categories})

    def category(request, category_slug):
        try:
            category_selected = Category.objects.get(slug=category_slug)
        except Category.DoesNotExist:
            category_selected = None
        albums = category_selected.albums.all()
        return render(request, 'category.html', {
            'category_selected': category_selected,
            'albums': albums
        })


    def album(request, category_slug, album_slug):
        try:
            category_selected = Category.objects.get(slug=category_slug)
            album_selected = Album.objects.get(slug=album_slug)
        except Category.DoesNotExist:
            category_selected = None
        except Album.DoesNotExist:
            album_selected = None
        posts = album_selected.posts.all()
        return render(request, 'album.html', {
            'category_selected': category_selected,
            'album_selected': album_selected,
            'posts': posts
        })

    ...

includedtemplate.html

...

{% for obj in objects %}

    ...    

    <a href="{% url view category_slug=obj.slug album_slug=obj.slug %}">

    ...

{% endfor %}

...

index.html

...

{% include 'includedtemplate.html' with objects=main_categories view='category' %}

...

EDIT: I've managed to solve this by separating my urls with only one different slug each. This is simpler and fits my situation better, considering that I had a M2M for Category and Album and this could cause many urls for a single album.

1 Answer 1

0

You can combine views and set None for album_slug.

def combined_view(request, category_slug, album_slug=None):

    category_selected = Category.objects.filter(slug=category_slug).first()
    album_selected = None
    posts = None
    template = 'category.html'

    if album_slug:
        album_selected = Album.objects.filter(slug=album_slug).first()
        posts = album_selected.posts.all()
        template = 'album.html'

    return render(request, template, {
        'category_selected': category_selected,
        'album_selected': album_selected,
        'posts': posts
    })

Also the order of urls is important - first url should be with one parameter, second with two parameters:

url(r'^portfolio/(?P<category_slug>[-\w]+)/$', views.combined_view, name='cview'),
url(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<album_slug>[-\w]+)/$', views.combined_view, name='cview'),

P.S. Instead of try..except in views you can use filter().first(). It is faster to write.

Sign up to request clarification or add additional context in comments.

2 Comments

First of all, sorry for the late answer. I tried your suggestion but it didn't work, something about the two url slugs. Althought, I did manage to solve by using only one different slug for each url, as this would fit me better, considering that I had a M2M for Category with Album and that way a single album could have multiple urls (not nice). Thanks.
You are welcome. In one of my projects such approach works fine, but for sure it can be implemented differently. Glad that you have found another solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.