Albert
Albert

Reputation: 95

Why can't I fully get the value which is a list in python dictionary (Django request)?

I have a form inside of which is a select tag with options, it looks like this:

<form method="POST">
    {% csrf_token %}
    <div class="row">
        <div class="col-sm-3">
            <h4 class="mb-0 mt-2">Title:</h4>
        </div>
        <div class="col-sm-9">
            <input type="text" name="title" class="form-control" placeholder="Blogpost Title">
        </div>
    </div>
    <hr>

    <div class="row">
        <div class="col-sm-3">
            <h4 class="mb-0 mt-2">Tags:</h4>
        </div>
        <div class="col-sm-9">
            <select class="form-select" name="tags" multiple aria-label="multiple select example" required>
                {% for tag in tags %}
                    <option value="{{tag.name}}">{{tag.name}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
    <hr>
    
    <div class="row">
        <div class="col-sm-3">
            <h4 class="mb-0 mt-2">Description:</h4>
        </div>
        <div class="col-sm-9">
            <textarea name="desc" class="form-control" id="exampleFormControlTextarea1" rows="4" placeholder="Blogpost Description (HTML supported)"></textarea>
        </div>
    </div>
    <hr>

    <div class="text-center">
        <button type="submit" class="btn btn-primary">Create</button>
    </div>
</form>

And this is my view, where I'm handling it:

def create_blogpost(request, id):
    user = User.objects.get(id=id)
    tags = Tag.objects.all()

    if request.method == 'POST':
        title = request.POST['title']
        blogpost_tags = request.POST['tags']
        desc = request.POST['desc']

        # BlogPost.objects.create(
        #     title=title,
        #     profile=user,
        #     tags=tags,
        #     desc=desc
        # )

    else:
        pass

    context = {
        'user': user,
        'tags': tags
    }
    return render(request, 'main/create_blogpost.html', context)

When I'm printing out request.POST it looks like this:

request.POST <QueryDict: {'csrfmiddlewaretoken': ['TOKEN'], 'title': ['blogpost title'], 'tags': ['Python', 'C++'], 'desc': ['']}>

Here I chose 2 tags: Python and C++, but when I'm printing out the variable blogpost_tags, it shows only the last element of the list, which in this case is C++.

Why is it happening? Am I doing something wrong?

Upvotes: 1

Views: 77

Answers (1)

Sepehr
Sepehr

Reputation: 317

Well actually this is a feature and nothing is wrong with your code, read this.

The reasoning behind this is that an API method should consistently return either a string or a list, but never both. The common case in web applications is for a form key to be associated with a single value, so that's what the [] syntax does. getlist() is there for the occasions (like yours) when you intend to use a key multiple times for a single value.

You can get the list like this:

blogpost_tags = request.POST.getlist('tags')

I hope this helped :)

Upvotes: 1

Related Questions