nmu
nmu

Reputation: 1519

What is the DRY way to manage complex querystrings in django?

In my django project I have two options that use querystrings to define a kind of list being fetched, e.g:

<a href="{% url 'index' %}?list=shopping">Shopping</a>
<a href="{% url 'index' %}?list=chores">Chores</a>

On top of that I also want to check which list has been selected by the user and make it appear bold in the UI. So

{% if 'shopping' in request.GET.list or not request.GET.list %}
    <b><a href="{% url 'index' %}?list=shopping">Shopping</a></b>
    <a href="{% url 'index' %}?list=chores">Chores</a>
{% elif 'chores' in request.GET.list %}
    <a href="{% url 'index' %}?list=shopping">Shopping</a>
    <b><a href="{% url 'index' %}?list=chores">Chores</a></b>
{% endif %}

What's really confusing me now, is in addition to Shopping and Chores I also want to have two sub-options that define the order of the list. New and Old, for instance. To me it seems like the only way of doing this is with another duplication of all the code.

{% if 'new' in request.GET.list %}
    {% if 'shopping' in request.GET.list or not request.GET.list %}
        <b><a href="{% url 'index' %}?list=shopping&order=new">Shopping</a></b>
        <a href="{% url 'index' %}?list=chores&order=new">Chores</a>
        <b><a href="{% url 'index' %}?list=shopping&order=new">New</a></b>
        <a href="{% url 'index' %}?list=shopping&order=old">Old</a>
    {% elif 'chores' in request.GET.list %}
        <a href="{% url 'index' %}?list=shopping&order=new">Shopping</a>
        <b><a href="{% url 'index' %}?list=chores&order=new">Chores</a></b>
        <b><a href="{% url 'index' %}?list=chores&order=new">New</a></b>
        <a href="{% url 'index' %}?list=chores&order=old">Old</a>
    {% endif %}
{% elif 'old' in request.GET.list %}
    {# ... #}
{% endif %}

I think you can already see how insane this becomes to manage and you would still need to do the same for the Old if statement. I really don't know what to do here because I can't see any other way to (1) Know what should be bold and not bold. And (2) Known whether each option should begin with a ? or &.

Upvotes: 1

Views: 40

Answers (2)

H&#229;ken Lid
H&#229;ken Lid

Reputation: 23074

You could use a QueryDict for your query strings. That's what Django uses internally.

https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.QueryDict

But really, I would consider refactoring your code. Put routing logic in your urls.py and business logic in your view functions. Try to keep the template files as uncomplicated as possible.

Instead of /?list=shopping you can use a regular url: /list/shopping/, for example.

Upvotes: 1

devdob
devdob

Reputation: 1504

Regarding your first problem with having bold selected value, by the use a of a HTML class you can do the following instead for example.

In your css file (or style block in your html file):

.selected {font-weight: bold;}

So your html can now become somehing like,

<a class="{% if 'shopping' in request.GET.list or not request.GET.list %} selected{% endif %}" href="{% url 'index' %}?list=shopping">Shopping</a>
<a class="{% if 'chores' in request.GET.list %}selected{% endif %}" href="{% url 'index' %}?list=chores">Chores</a>

This way you dont have to write your html twice or more for each case.

As for your second issue, you can do something like below if you are using your 'new' and 'old' in your urls or html,

{% with 'new old bla' as list %}
    {% for option in list.split %}
       <a class="{% if 'shopping' in request.GET.list or not request.GET.list %} selected{% endif %}" href="{% url 'index' %}?list=shopping&option={{ option }}">Shopping</a>
       <a class="{% if 'chores' in request.GET.list %}selected{% endif %}" href="{% url 'index' %}?list=chores&option={{ option }}">Chores</a>

    {% endfor %}
{% endwith %}

Thats just an example of how you would use it, but this will save alot of code writing.

Hope this helps!

Upvotes: 1

Related Questions