Django调用REST API时出现UnboundLocalError问题求助
Problem Description
I'm trying to fetch a company_id from the result of cwObj.get_company(company), then pass that company_id to cwObj.get_sites(company_id) to retrieve site data. When I debug, I can see company_id has the expected value, but calling get_sites triggers an UnboundLocalError. I'm confused—does this mean the variable wasn't properly assigned? What's the best practice for assigning variables before making such API calls?
Relevant Code
views.py
def new_opportunity_location(request): company = request.GET.get('selected_company') company_obj = cwObj.get_company(company) company_id = company_obj[0]['id'] sites = cwObj.get_sites(company_id) context = {'sites': sites} return render(request, 'website/new_opportunity_location.html', context)
API Client Methods
def get_company(self, request): try: r = requests.get( self.URL + 'company/companies?conditions=name="' + request + '"', headers=self.Header) r.raise_for_status() except: print(r.text) raise return r.json() def get_sites(self, request): try: r = requests.get( self.URL + 'company/companies/' + request + '/sites', headers=self.Header) r.raise_for_status() except: print(r.text) raise return r.json()
Solution & Explanation
First, let's clear up your confusion: your company_id variable is almost certainly properly assigned (since you can see its value in debug). The UnboundLocalError is actually coming from a bug in your exception handling code, not from the company_id variable itself.
The Root Cause
Look at the except blocks in both get_company and get_sites:
except: print(r.text) raise
If the requests.get() call fails before assigning the response to r (e.g., a DNS failure, network timeout, or invalid URL construction), the r variable won't exist in the scope of the except block. When you try to print r.text, Python throws an UnboundLocalError because r hasn't been defined yet.
This makes it look like the error is related to passing company_id, but it's actually a separate issue with your error handling.
Fix the Exception Handling
Update your API client methods to avoid referencing r unless you know it's been assigned. Here's a better approach:
def get_company(self, company_name): # Rename parameter to avoid confusion with Django's request object url = f"{self.URL}company/companies?conditions=name=\"{company_name}\"" try: r = requests.get(url, headers=self.Header) r.raise_for_status() except requests.exceptions.RequestException as e: # Handle all requests-related exceptions explicitly if 'r' in locals(): print(f"API Error Response: {r.text}") print(f"Request Failed: {str(e)}") raise return r.json() def get_sites(self, company_id): # Rename parameter for clarity, convert to string to avoid type issues company_id_str = str(company_id) url = f"{self.URL}company/companies/{company_id_str}/sites" try: r = requests.get(url, headers=self.Header) r.raise_for_status() except requests.exceptions.RequestException as e: if 'r' in locals(): print(f"API Error Response: {r.text}") print(f"Request Failed: {str(e)}") raise return r.json()
Best Practices for Variable Assignment Before API Calls
- Validate and sanitize inputs
Check thatcompany = request.GET.get('selected_company')is notNonebefore passing it toget_company. Add a guard clause:company = request.GET.get('selected_company') if not company: # Handle missing company parameter (e.g., return 400 Bad Request) return HttpResponseBadRequest("Selected company is required") - Handle empty/non-existent API results
company_obj = cwObj.get_company(company)could return an empty list if no matching company is found. Add a check:if not company_obj: return HttpResponseNotFound("Company not found") company_id = company_obj[0]['id'] - Use type conversion explicitly
Ifcompany_idis an integer, convert it to a string before concatenating into the URL (as shown in the fixedget_sitesmethod) to avoidTypeError. - Avoid generic exception handlers
Catching all exceptions withexcept:is bad practice—it can hide unexpected errors. Instead, catch specific exceptions likerequests.exceptions.RequestExceptionto handle API-related issues. - Rename parameters for clarity
Usingrequestas a parameter name in your API client methods is confusing because it clashes with Django'sHttpRequestobject. Use descriptive names likecompany_nameorcompany_idinstead.
内容的提问来源于stack exchange,提问作者garmars

