0

Trying to create a django application but getting an UnboundLocalError at /search/ local variable 'results' referenced before assignment error. I can't see the problem as in my code results is assigned - have a look:

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()
    return render(request, 'blog/post/search.html', {'form': form,
                                                 'cd': cd,
                                                 'results': results,
                                                 'total_results': total_results})
lennyklb
  • 1,307
  • 2
  • 15
  • 32
Milo.D
  • 355
  • 1
  • 4
  • 15
  • I'm really new to Django - just following a tutorial – Milo.D Apr 11 '17 at 10:22
  • What should I do to fix it – Milo.D Apr 11 '17 at 10:23
  • 2
    But that's just a basic Python thing, it's got nothing to do with Django. Are you also new to Python? – PM 2Ring Apr 11 '17 at 10:23
  • Fairly - I understand what you are saying - the variable is not created unless the form is valid, and since it can't be valid until it is created it doesn't work. – Milo.D Apr 11 '17 at 10:25
  • So put the `render()` call inside the `if` block rather than in the `return` statement. If the form is invalid, presumably you want to display an error message, or at least log the error. – PM 2Ring Apr 11 '17 at 10:31

5 Answers5

2

Maybe you should initialize results. Put results = [] before if form.is_valid()

Dmitry Loparev
  • 462
  • 2
  • 9
2

It depends on what you want to do if there are no results. Do you still want to load the view? Then initialise the results variable above any if condition (in this case, the outer one):

...
results = [] #Or whatever empty datatype you need
if 'query' in request.GET:
   ...

If you don't want to load the view if there are no results, you could move the return render(...) inside the inner if when you're sure there is a results variable to begin with. Then, you can add a fallback return render(...) at the end of the function, outside of any if conditions.

If you always want to load the same view, however, I'd just go for the first one. Adding multiple return render(...) seems more suitable when you want to load a different view when no results were found.

lennyklb
  • 1,307
  • 2
  • 15
  • 32
2

What if form is invalid? For example, user provided incorrect value on no value at all? In this case results is uninitialized. You may:

  1. Initialize it with some empty value like [].

  2. Raise error and return to user info that form is invalid.

Eugene Lisitsky
  • 12,113
  • 5
  • 38
  • 59
1
def post_search(request):
    cd = ""
    total_results = ""
    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()
    return render(request, 'blog/post/search.html', {'form': form,
                                                 'cd': cd,
                                                 'results': results,
                                                 'total_results': total_results})

now you have to write validation code in template

mahendra kamble
  • 1,375
  • 1
  • 14
  • 24
0

If you want to use the definition in a recursive way(count the results in your case) you should assign the var results outside the definition, because if you do it will reset every time you call it. You have to assign it out of the definition and state it like a global var.

global results 
results = ''

I personally recommend you to do a bit more reading and learning on python before coding with Django.

Good luck ! :)

Pedro Gomes
  • 196
  • 1
  • 15
  • There is almost never a reason to declare global variables in python. A simple result variable in this case can easily be handled within the scope of this function. – lennyklb Apr 11 '17 at 17:38
  • Can you please be a little more specific ? If he wants to do iteration with the function, the var result will be reset every time the function is called, plus if the var results is declared as global, it can be used in other functions and the value the var got on the first function isn't changed in the ones to come. That's why I proposed to declare the var results as global. – Pedro Gomes Apr 12 '17 at 11:24
  • "If he wants to do iteration with the function" What do you mean by this? – lennyklb Apr 12 '17 at 15:42
  • This function loads a view. The results are queried from the database to probably be formatted into some template. If this value is so essential it needs to be accessible from anywhere, it should not even be initialised here, but someplace else. Using a global variable for this is pointless. You can read more on this [here][http://stackoverflow.com/questions/19158339/why-are-global-variables-evil] – lennyklb Apr 12 '17 at 15:45