def check():
if 3>2:
return redirect(url_for('control'))
#app.route('/reason', methods=['GET','POST'])
def reason():
check()
return render_template('reason.html')
#app.route('/control', methods=['GET','POST']
def control():
return render_template('control.html')
I have two html files (control.html and reason.html). the code loads reason.html page first and receives user input using POST method then after doing certain checks, I want to reload control.html.
the problem is I am not able to load control.html
You are ignoring the return value from check(). Consequently, the object that will signal a redirect is simply lost.
You should inspect the return value from check() and either return that result, or the 'reason.html' result:
# UNTESTED
#app.route('/reason', methods=['GET','POST'])
def reason():
check_result = check()
if check_result:
return check_result
return render_template('reason.html')
On a related note, your check() has two return paths. One explicitly invokes return, the other implicitly returns None as it falls off the end of the function. This is perfectly legal, but confusing stylistically. Try this:
def check():
if 3>2:
return redirect(url_for('control'))
return None
Perhaps a more understandable code arrangement would be to have check limit its responsibilities to simply checking and reporting the result; then reason() can be responsible for whatever page is displayed, like so:
#UNTESTED
def check():
if 3>2:
return True
return False
# UNTESTED
#app.route('/reason', methods=['GET','POST'])
def reason():
if check():
return redirect(url_for('control'))
return render_template('reason.html')
Related
I want to be able to mock a function that mutates an argument, and that it's mutation is relevant in order for the code to continue executing correctly.
Consider the following code:
def mutate_my_dict(mutable_dict):
if os.path.exists("a.txt"):
mutable_dict["new_key"] = "new_value"
return True
def function_under_test():
my_dict = {"key": "value"}
if mutate_my_dict(my_dict):
return my_dict["new_key"]
return "No Key"
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.return_value = True
result = function_under_test()
assert result == "new_value"
**Please understand i know i can just mock os.path.exists in this case but this is just an example. I intentionally want to mock the function and not the external module.
**
I also read the docs here:
https://docs.python.org/3/library/unittest.mock-examples.html#coping-with-mutable-arguments
But it doesn't seem to fit in my case.
This is the test i've written so far, but it obviously doesn't work since the key changes:
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.return_value = True
result = function_under_test()
assert result == "new_value"
Thanks in advance for all of your time :)
With the help of Peter i managed to come up with this final test:
def mock_mutate_my_dict(my_dict):
my_dict["new_key"] = "new_value"
return True
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.side_effect = mock_mutate_my_dict
result = function_under_test()
assert result == "new_value"
How it works is that with a side effect you can run a function instead of the intended function.
In this function you need to both change all of the mutating arguments and return the value returned.
I am trying to understand python decorators so I decided to check the inner workings of django #login_required decorator. After looking at the source code, I got here:
def user_passes_test(test_func, login_url=None,
redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
From what I understand, the above function is supposed to use the return value of test_func to determine whether to redirect user to login page or allow user to continue. My problem is that i can't find anywhere this test_func is called. How does the above function user_passes_test work exactly. Any help will be appreciated.
edit:
I have realized that I am the problem since I was looking at the source code on django documentation and I have just noticed that there is an indentation error. Am all good now.
It's called in this line.
To explain what's going on, let's use a simpler example. Assume you have various functions (corresponding to the views) that need to have their arguments checked (corresponding to the user check) before being executed; if the arguments fail the check, the result should be None (corresponding to the login redirect).
Here's example code, the structure of which matches Django's user_passes_test:
def arguments_pass_test(test_func):
def decorator(func):
def _wrapped_func(*args, **kwargs):
if test_func(*args, **kwargs):
return func(*args, **kwargs)
else:
return None
return _wrapped_func
return decorator
#arguments_pass_test(lambda x: x != 0)
def inverse(x):
return 1.0 / x
print(inverse(2)) # 0.5
print(inverse(0)) # None
So let's look at how the decorator magic happens, that is this part:
#arguments_pass_test(lambda x: x != 0)
def inverse(x):
return 1.0 / x
First off, arguments_pass_test(lambda x: x != 0) is just a function call; the # doesn't come into play yet. The return value from that function call to arguments_pass_test is the inner function called decorator, and the naming makes it clear that this function is the actual decorator.
So now we have this:
#decorator
def inverse(x):
return 1.0 / x
The decorator syntax gets translated by Python into something roughly equivalent to this:
def inverse(x):
return 1.0 / x
inverse = decorator(inverse)
So inverse gets replaced with the the result of calling the decorator with the original function inverse as its argument func. The result of calling the decorator is what's called _wrapped_func. So what's happening is similar to this:
def _original_inverse(x):
return 1.0 / x
def _wrapped_func(x):
if test_func(x): # this doesn't exist here, but bear with me
return _original_inverse(x)
else
return None
inverse = _wrapped_func
which is finally equivalent(ish) to
def inverse(x):
if x != 0:
return 1.0 / x
else
return None
which is exactly what we were going for.
I'm not sure where you got that function, but I just freshly install django through pip on my Python 3.6, and here is what I found in django.contrib.auth.decorators. The following is accessible here as well.
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
def decorator(view_func):
#wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
path, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator
This makes much more sense, since test_func is effectively called inside of the decorator.
I'm writing a driver in Python 2.6 and I need it to be reverse compatible with a previous implementation (I don't have access to the source code).
class new_driver ():
def output(self, state):
if state == True:
self.set_ouput_on()
else:
self.set_output_off()
...
The odd thing is that to keep compatibility I have to pass this output using the format
nd = new_driver()
nd.output = True
How do I pass a value in this way?
Edit: To clarify: my "output" function has to receive the value True in this way in order to execute the function self.set_output_on()
Try using the #property decorator:
#property
def output(self):
return self... #not sure how you are tracking output on/off
#output.setter
def output(self, state):
if state:
self.set_output_on()
else:
self.set_output_off()
The views.py somthing like this
def getFormValues(request):
if ('mobile_a' in request.GET and request.GET['mobile_a']) and ('mobile_b' in request.GET and request.GET['mobile_b']):
mobile_a = request.GET['mobile_a']
mobile_b =request.GET['mobile_b']
# calling the mark calculation function
return calculateMark(mobile_a, mobile_b)
else:
message ='You submitted an empty form.'
return HttpResponse(message)
Here I am calling a function(calculateMark) which will calculate a marking. In the end of the calculateMark function I have something like this
if (tech_mark_a == 0 and tech_mark_b == 0):
mobile_a_infos = TechSpecificationAdd.objects.filter(tech_variables)
return render_to_response('degrees_result.html', {'mobile_a': tech_mark_a, 'mobile_b': mobile_b}, mobile_a_infos)
elif (tech_mark_a > 0 and tech_mark_b > 0):
return render_to_response('degrees_result.html', {'mobile_a': tech_mark_a, 'mobile_b': mobile_b})
The Problem is when I am submitting an empty form It's showing the message as getFormValues(). But when I submit something on the form it's showing an error The view MarkCalculation.views.getFormValues didn't return an HttpResponse object.
How can I solve the problem? Thanks in advance.
Fix your calculateMark() function so that it doesn't have any code paths that don't return a response. Also, consider converting the arguments to numbers first.
EDIT: FWIW, I am running django 1.3
I have...
class CreateProductWizard(FormWizard):
def get_template(self, step):
if step == 1:
return 'product/form_wizard/editor.html'
else:
return 'product/form_wizard/wizard_%s.html' % step
def process_step(self, request, form, step):
if step == 1:
self.extra_context = {'ptype': form.cleaned_data}
return
else:
return
def done(self, request, form_list):
# now that it's all together, store it.
return render_to_response('product/form_wizard/done.html',
{'form_data': [form.cleaned_data for form in form_list]},
context_instance=RequestContext(request))
and I'd like to get the self.extra_context to the template.
How do I get that on the template?
I've tried on the template:
{{extra_context}}
{{form.extra_context}}
{{form.extra_context.ptype}}
etc..
Looking at the docs i'd say that get_context_data is what you are after:
Returns the template context for a step. You can overwrite this method
to add more data for all or some steps. This method returns a
dictionary containing the rendered form step.
So what I ended up using on the template was:
{{ptype}}
which I had already tried.
The problem, and I'm still not sure why was that I had:
def process_step(self, request, form, step):
if step == 1:
self.extra_context = {'ptype': form.cleaned_data}
return
else:
return
and what worked was:
def process_step(self, request, form, step):
self.extra_context = {'ptype': 'hello!!',}
For some reason, the 'step' that is being passed to 'process_step()' is always == 0 which made my 'if step ==1:' logic fail...
After reviewing the source (django.contrib.formtools.wizard.FormWizard), one thing that looks like it could be failing on is my form is not valid. It must be valid for the step number to increment and call the process_step function. HOWEVER, the {{step}} variable is getting the right value. And I'm not doing anything crazy with the form...
So weird. But my main question is solved.