I am trying to make an API endpoint that will take input like http://127.0.0.1:8000/getslots?car_number=3and give output as car_number or slot_parking. Here is what I have done:
slots = {'ka9865': 1, 'ka9866': 2, 'ka9867': 3}
def get_car(request):
if request.method == 'GET':
try:
car_number = request.GET['car_number']
for key,value in slots.items():
if key == car_number:
car_slot = value
response = json.dumps([{'slot': car_slot}])
except (UnboundLocalError):
slot = request.GET['car_number']
for key,value in slots.items():
if value == slot:
car_number1 = key #not entering inside this loop
response = json.dumps([{ 'car_number': car_number1}])
except:
response = json.dumps([{ 'Error': 'No car with that name/slot'}])
return HttpResponse(response, content_type='text/json')
But I am getting error of UnboundLocalError: local variable 'response' referenced before assignment
I am not able to figure out how to do this and also please suggest me if there is any better way of implementing this.
Thank you.
You need to creatwe response already before otherwise the variable will be just in the namespace of the exception block.
slots = {'ka9865': 1, 'ka9866': 2, 'ka9867': 3}
def get_car(request):
response = None # Create default reponse here
if request.method == 'GET':
#...
Related
def func(name):
ddb = session.resource(service_name="dynamodb")
table = ddb.Table("TABLE_X")
response = table.get_item(Key={"employee": user})
data = response["Item"]
for item in data.items():
if data["employee"] == name:
manager = data["manager"]
return name, manager
return False
ddb table has:
employee
manager
Jane
John
Ben
Mike
I want to be able to say, if user does not exist, return no user found.
I understand that it will return Key error if it doesn't exist, so how can I achieve that in a way that it will return me an output no user found instead of the key error?
You can check if a key is in a dictionary with 'foo' in bar. So judging from the comments you want to return False and print an error message if something is not found.
explicit check
For each key you want, check if it exists:
def func(name):
ddb = session.resource(service_name="dynamodb")
table = ddb.Table("TABLE_X")
response = table.get_item(Key={"employee": user})
if not 'Item' in response:
print('User not found')
return False
data = response["Item"]
for item in data.items():
if "employee" in data and data["employee"] == name:
manager = data["manager"]
return name, manager
return False
Implicit check (catch the error)*
The method above has a high likelyhood of missing an occetion to check ... There is a python build in way to deal with expected errors...
def func(name):
try:
ddb = session.resource(service_name="dynamodb")
table = ddb.Table("TABLE_X")
response = table.get_item(Key={"employee": user})
data = response["Item"]
for item in data.items():
if data["employee"] == name:
manager = data["manager"]
return name, manager
return False
except KeyError as e:
print('User could not be found. Original error:', e.message)
return False
I'm having trouble getting the updated value of a class variable.
When ConnectTestAPI is called after the p_request function is executed, the class variables which are result and orderNo should updated in the post function.
Then I want to receive the updated value of class variables by looping while statement in the p_request function.
However, despite setting the values of class variables with the post request, when the while statement is run, the corresponding values are still empty and 0 value respectively,
So, the while statement cannot be terminated and results in a time out error.
Here is my source code. Thank you in advance!
class ConnectTestAPI(APIView):
result=""
orderNo=0
def post(self, request):
data = request.data
ConnectTestAPI.result = data['result']
ConnectTestAPI.orderNo = data['orderNo']
print(ConnectTestAPI.result) # I could successfully get data from POST request here!
print(ConnectTestAPI.orderNo) # I could successfully get data from POST request here!
return HttpResponse("ok")
def p_request():
data = {
"a" : 1234,
"b" : 5678
}
data = json.dumps(data,ensure_ascii=False).encode('utf-8')
con = redis.StrictRedis(outside_server['ip'],outside_server['port'])
con.set("data_dict", data)
while True:
if ConnectTestAPI.result != "" and ConnectTestAPI.orderNo != 0:
break
res_result = ConnectTestAPI.result
res_orderNo = ConnectTestAPI.orderNo
return res_result, res_orderNo
You need to access the class variables using self:
class ConnectTestAPI(APIView):
result=""
orderNo=0
def post(self, request):
data = request.data
self.result = data['result']
self.orderNo = data['orderNo']
print(self.result) # I could successfully get data from POST request here!
print(self.orderNo) # I could successfully get data from POST request here!
return HttpResponse("ok")
def p_request():
data = {
"a" : 1234,
"b" : 5678
}
data = json.dumps(data,ensure_ascii=False).encode('utf-8')
con = redis.StrictRedis(outside_server['ip'],outside_server['port'])
con.set("data_dict", data)
while True:
if self.result != "" and self.orderNo != 0:
break
res_result = self.result
res_orderNo = self.orderNo
return res_result, res_orderNo
NOTE: This usage of class attributes is not recommended. You are mutating a class attribute which has side effects on all instances of that class. In your case, an ordinary attribute initialized within __ init__() would be ok:
class ConnectTestAPI(APIView):
def __init__(self):
self.result=""
self.orderNo=0
def post(self, request):
data = request.data
self.result = data['result']
self.orderNo = data['orderNo']
print(self.result) # I could successfully get data from POST request here!
print(self.orderNo) # I could successfully get data from POST request here!
return HttpResponse("ok")
def p_request():
data = {
"a" : 1234,
"b" : 5678
}
data = json.dumps(data,ensure_ascii=False).encode('utf-8')
con = redis.StrictRedis(outside_server['ip'],outside_server['port'])
con.set("data_dict", data)
while True:
if self.result != "" and self.orderNo != 0:
break
res_result = self.result
res_orderNo = self.orderNo
return res_result, res_orderNo
I am using Signalr Core client in Python by: https://github.com/mandrewcito/signalrcore
I am using chat example from the git source above and modified it for my application.
I am trying to put a while loop in a function, where the condition of while loop should break when another function is called. But it gets stuck in the while loop.
Here is my code:
from signalrcore.hub_connection_builder import HubConnectionBuilder
def input_with_default(input_text, default_value):
value = input(input_text.format(default_value))
return default_value if value is None or value.strip() == "" else value
def start_msg(msg):
while end_event.has_been_called == False:
Print("Starting")
sleep(1)
def end_event(endmsg):
end_event.has_been_called = True
pass
print("End Event")
server_url = input_with_default('Enter your server url(default: {0}): ', "ws://localhost:62342/chathub")
username = input_with_default('Enter your username (default: {0}): ', "sam")
hub_connection = HubConnectionBuilder().with_url(server_url).with_automatic_reconnect({
"type": "raw",
"keep_alive_interval": 10,
"reconnect_interval": 5,
"max_attempts": 5
}).build()
end_event.has_been_called = False
hub_connection.on("StartEvent", start_msg)
hub_connection.on("EndEvent", end_event)
hub_connection.start()
message = None
# Do login
while message != "exit()":
message = input(">> ")
if message is not None and message is not "" and message is not "exit()":
hub_connection.send("SendMessage", [username, message])
hub_connection.stop()
In this code, when it receives a message with StartEvent, it goes into start_msg function and starts printing "Starting", but as soon as EndEvent is received it should go to end_event function but it just gets stuck in while loop and never breaks out of it.
If I remove the while loop then it works fine, but I need it to stay in while loop inside start_msg until end_event is called.
How can I achieve this?
Edit: Just to clarify, I am referring to this while loop:
def start_msg(msg):
while end_event.has_been_called == False:
Print("Starting")
sleep(1)
Firstly, I would address your if statement
Rather than complicating your if statement, assign a list
conditions = [None, "", "exit()"]
Then you can do
if message not in conditions:
Which would allow you to expand your conditions if you had to. Also a little more elegant IMO
Secondly, I would make this a class. end_event.has_been_called is assigning an attribute to a function, which is wierd.
Lastly, Your start event should call your end event. Unless this module runs async somehow (I did not install it), you will never get to your end_event function call, so you're stuck in your loop. Hope this helps
from signalrcore.hub_connection_builder import HubConnectionBuilder
class Event_Handler:
def __init__(self):
self.conditions = [None, "", "exit()"]
self.end_call = False
def input_with_default(self, input_text, default_value):
value = input(input_text.format(default_value))
return default_value if value is None or value.strip() == "" else value
def start_msg(self, msg):
while self.end_call == False:
print("Starting")
self.end_event('Ending')
sleep(1)
def end_event(self, endmsg):
self.end_call = True
pass
print("End Event")
def run_server(self):
server_url = input_with_default('Enter your server url(default: {0}): ', "ws://localhost:62342/chathub")
username = input_with_default('Enter your username (default: {0}): ', "sam")
hub_connection = HubConnectionBuilder().with_url(server_url).with_automatic_reconnect({
"type": "raw",
"keep_alive_interval": 10,
"reconnect_interval": 5,
"max_attempts": 5
}).build()
self.end_call = False
hub_connection.on("StartEvent", start_msg)
hub_connection.on("EndEvent", end_event)
hub_connection.start()
message = None
# Do login
while message != "exit()":
message = input(">> ")
if message not in self.conditions:
hub_connection.send("SendMessage", [username, message])
hub_connection.stop()
I have an app that shows some questions to the user. It has to reply in input text fields and then there's a view that checks all these results (the one below).
This view perfectly works but I know I made a mess with dictionaries and lists. I thought to create those just to prepare a results variable that then I'll print on the HTML page. How can I simplify it?
def check(request):
# Initialize results
results = []
i = 0
for input_name, input_value in request.POST.items():
# Remove cfsr from inputs
if input_name.isdigit():
# Get the question from the input name
question = Question.objects.get(pk=input_name)
# Get the related correct answer to that question
answer = question.answer
# Create results
results.append({'question_text': question.text, 'user_answer': input_value,
'correct_answer': answer.text})
# Check if user answer is correct
if input_value == answer.text:
results[i]['is_correct'] = True
else:
results[i]['is_correct'] = False
i += 1
context = {'results': results}
return render(request, 'quiz/results.html', context)
You could make these improvements for readability:
Create a list of the inputs that you want to access; the if check for the csrf_token field makes the code more difficult to read, and the assumption that csrf_token always contains letters may not be true.
Remove the counter variable (i); counters like this in for loops aren't pythonic, and often just complicate the code.
Replace the if/else test for the correct answer with a boolean expression; you can always to this with if/else blocks that simply assign True or False to a variable depending on the result of some test.
Build your results dictionary completely before appending to the list to avoid having to access via its index (results[i]...).
from django.http import HttpResponseNotAllowed, HttpResponseBadRequest
def check(request):
if not request.method == 'POST':
return HttpResponseNotAllowed(['POST'])
# guaranteed by CsrfViewMiddleware to exist
del request.POST['csrfmiddlewaretoken']
results = []
for question_id, user_answer in request.POST.items():
try:
question = Question.objects.get(pk=name)
except Question.DoesNotExist:
return HttpResponseBadRequest("Oops!")
results.append({
'question_text': question.text,
'user_answer': user_answer,
'correct_answer': question.answer.text,
'is_correct': value == question.answer.text,
})
return render(request, 'quiz/results.html', {
'results': results,
})
You can replace
if input_value == answer.text:
results[i]['is_correct'] = True
else:
results[i]['is_correct'] = False
with
results[-1]['is_correct'] = input_value == answer.text
and get rid of the i
or even better you could put that in the results.append
results.append({'question_text': question.text,
'user_answer': input_value,
'correct_answer': answer.text,
'is_correct': input_value == answer.text})
This is a rather silly issue but I stepped through the function but couldn't figure out what was causing the issue.
I was dynamically adding an attribute to the object I fetched from the db via SQLAlchemy and the objects were appended fine right before the return render_template was called, all but the last appended attribute in the variable from the list of found_survey.questions was lost. I.e. found_survey.questions[0].choices doesn't exist (but it did at one point), but found_survey.questions[-1].choices does.
I cannot seem to figure out what is going on... I thought it might be funky because of the database object (since I didn't commit survey, but I don't intend to, I was just appending the value so it's passed to the view with the correct logic).
Thanks so much for the help; I'm really stuck...
#app.route('/survey/<survey_id>', methods=['GET', 'POST'])
#login_required
def survey(survey_id):
form = UserSubmitForm()
found_survey = Survey.query.filter_by(id=survey_id).first()
if request.method == 'POST' and form.validate_on_submit():
print("input", form.answer_raw.data, form.category_list.data)
user_answer = Answer(note=found_survey.name,
answer_raw=form.answer_raw.data,
timestamp=datetime.utcnow(),
ip=request.remote_addr)
user_answer.user_id = g.user.id
user_answer.survey_id = survey_id
# other processing omitted
db.session.add(user_answer)
elif request.method != "POST":
for q in found_survey.questions:
q.choices = []
text_list = q.choice_text_string.split(',')
value_list = q.choice_value_string.split(',')
for i, text in enumerate(text_list):
q.choices.append((text, value_list[i]))
return render_template('survey.html',
form=form,
survey=found_survey,
is_editing=False)
Wouldn't it just be simpler to do this:
annotated_obj = []
for q in found_survey.questions:
text_list = q.choice_text_string.split(',')
value_list = q.choice_value_string.split(',')
question_choices = {}
for i, text in enumerate(text_list):
question_choices.setdefault(text, []).append(value_list[i])
annotated_obj.append((q, question_choices))