简体   繁体   中英

I keep getting the following error “local variable 'total_results' referenced before assignment”

I am new to django and python, I am following a django tutorial and I keep getting the following error

UnboundLocalError at /blog/search/
local variable 'total_results' referenced before assignment

heres my code

 def post_search(request):
        form = SearchForm()
        if 'query' in request.GET:
            form = SearchForm(request.GET)
            if form.is_valid():
                cd = form.cleaned_data
                results = SearchQuerySet().models(Post)\
                    .filter(content=cd['query']).load_all()
                # count total results
                total_results = results.count()
        template = 'blog/post/search.html'
        context = {
           'form': form,
           'cd': cd,
           'results': results,
           'total_results': total_results
        }
        return render(request, template, context)

I also tried it like this origanally because that's how the tutorial had it

 return render(request, template, {
    'form': form,
    'cd': cd,
    'results': results,
    'total_results': total_results
  })

but that also didn't work

I understand what the error message is saying but this is how the tutorial has it. What's the proper syntax to make this work. all guidance is welcome

EDIT: here is the template code

   {% extends "blog/base.html" %}
       {% block title %}Search{% endblock %}
       {% block content %}
         {% if "query" in request.GET %}
           <h1>Posts containing "{{ cd.query }}"</h1>
           <h3>Found {{ total_results }} result{{ total_results|pluralize}}</h3>
           {% for result in results %}
             {% with post=result.object %}
               <h4><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h4>
               {{ post.body|truncatewords:5 }}
             {% endwith %}
     {% empty %}
    <p>There are no results for your query.</p>
           {% endfor %}
           <p><a href="{% url 'blog:post_search' %}">Search again</a></p>
         {% else %}
           <h1>Search for posts</h1>
           <form action="." method="get">
             {{ form.as_p }}
             <input type="submit" value="Search">
           </form>
         {% endif %}
       {% endblock %}

If there would not be query GET parameter passed, or the form would not pass validation - in this case total_results and results would not be defined. You need to either provide the default values for that case, eg:

def post_search(request):
    results = []
    total_results = 0

    form = SearchForm()
    if 'query' in request.GET:
        form = SearchForm(request.GET)
        if form.is_valid():
            cd = form.cleaned_data
            results = SearchQuerySet().models(Post)\
                .filter(content=cd['query']).load_all()
            # count total results
            total_results = results.count()
    template = 'blog/post/search.html'
    context = {
       'form': form,
       'cd': cd,
       'results': results,
       'total_results': total_results
    }
    return render(request, template, context)

Or, throw a specific "validation" error in case there is no query parameter or form is not valid.

def post_search(request):
    results = []  # or None
    total_results = 0  # or None
    form = SearchForm(request.GET or None)
    if 'query' in request.GET:

        if form.is_valid():
            cd = form.cleaned_data
            results = SearchQuerySet().models(Post)\
                .filter(content=cd['query']).load_all()
            # count total results
            total_results = results.count()
            template = 'blog/post/search.html'
            context = {
               'form': form,
               'cd': cd,
               'results': results,
               'total_results': total_results
                    }
               return render(request, template, context)
       else:
            return render(request, 'blog/post/search.html', {'form': form,})
    else:
       return render(request, 'blog/post/search.html', {'form': form,})

Python is pointing out that what will happen if the 'if' condition fails, and still you are using the variable 'total_results' in context. Therefore initialize it as 0 or none as you want. Similar with the 'results' variable too.

EDIT1: Since i don't exactly know what you are trying to achieve, my best guess would be to use this code.

EDIT2: Template code changes

{% extends "blog/base.html" %}
   {% block title %}Search{% endblock %}
   {% block content %}
     {% if results %}
       <h1>Posts containing "{{ cd.query }}"</h1>
       <h3>Found {{ total_results }} result{{ total_results|pluralize}}</h3>
       {% for result in results %}
         {% with post=result.object %}
           <h4><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h4>
           {{ post.body|truncatewords:5 }}
         {% endwith %}
 {% empty %}

<p>There are no results for your query.</p>
       {% endfor %}

       <p><a href="{% url 'blog:post_search' %}">Search again</a></p>
     {% else %}
       <h1>Search for posts</h1>
       <form action="." method="get">
         {{ form.as_p }}
         <input type="submit" value="Search">
       </form>
     {% endif %}
   {% endblock %}

I've gone through the same book, and noticed the same problem with that particular view. Here was my solution in the view. I left the template the way it was (in the book):

def post_search(request):
    if 'query' in request.GET:
        form = SearchForm(request.GET)
        if form.is_valid():
            cd = form.cleaned_data
            results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
            total_results = results.count()
            context = {'form':form, 'cd':cd, 'results':results, 'total_results':total_results}
            return render (request, 'blog/post/search.html', context)
    else:
        form = SearchForm()
        context = {'form':form}
        return render (request, 'blog/post/search.html', context)

had exactly the same issue ... the code below works

    def post_search(request):
        results = []
        total_results = 0
        cd = None
        form = SearchForm()
        if 'query' in request.GET:
            form = SearchForm(request.GET)
            if form.is_valid():
            cd = form.cleaned_data
            results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()    
        total_results = results.count()
    return render(request, 'search/search.html', {'form':form,
                                               'cd':cd,
                                               'results':results,
                                               'total_results':total_results,
                                               })

But out of interest did you also find that the post_detail view produced similar errors ?? solved that one with this version of the code

    def post_detail(request, year, month, day, post):


        post = get_object_or_404(Post, slug=post,
                                   status='published',
                                   publish__year=year,
                                   publish__month=month,
                                   publish__day=day)


    #list of active comments for this post
    comments = post.comments.filter(active=True)

    if request.method == 'POST':
        # A comment was posted
        comment_form = CommentForm(data=request.POST)
        if comment_form.is_valid():
            #create comment object but don't save to DB
            new_comment = comment_form.save(commit=False)
            # assitgn comment to post
            new_comment.post = post
            # save the comment to the DB
            new_comment.save()

    else:
        comment_form =CommentForm()





   post_tags_ids = post.tags.values_list('id', flat=True)
   similar_posts =    Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
   similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:4]


   args = {}
   args['post'] = post 
   args['comment_form']= comment_form
   args['comments'] = comments 
   args['similar_posts'] = similar_posts
   return render(request, 'detail.html', args )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM