I'm sure I'm missing something hideously obvious here, but this test is currently failing:
def test_index_view_returns_correct_html_document(self):
request = HttpRequest()
response = LogIn(request)
expected_html = render_to_string('login.html')
self.assertEqual(response.content, expected_html)
It fails with the error ''HttpRequest' object has no attribute 'user''
The view that's being tested has this piece of code that checks whether a user is currently logged in, and throws a redirect if so:
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('index'))
What am I missing? I've looked in the docs but can't seem to find an explanation. I'm sure it's something obvious. Or I'm doing something wrong.
You've just constructed a bare request and passed it to the function, so it hasn't gone through any of the middleware - including the authentication one that adds the user object.
You should probably use the test client for this test, as it simulates the whole request/response cycle.
Related
When the class AnonUser is initialized, the code should check if a cookie exists and create a new one if it doesn't. The relevant code snippet is the following:
class AnonUser(object):
"""Anonymous/non-logged in user handling"""
cookie_name = 'anon_user_v1'
def __init__(self):
self.cookie = request.cookies.get(self.cookie_name)
if self.cookie:
self.anon_id = verify_cookie(self.cookie)
else:
self.anon_id, self.cookie = create_signed_cookie()
res = make_response()
res.set_cookie(self.cookie_name, self.cookie)
For some reason, request.cookies.get(self.cookie_name) always returns None. Even if I log "request.cookies" immediately after res.set_cookie, the cookie is not there.
The strange thing is that this code works on another branch with identical code and, as far as I can tell, identical configuration settings (it's not impossible I'm missing something, but I've been searching for the past couple hours for any difference with no luck). The only thing different seems to be the domain.
Does anyone know why this might happen?
I figured out what the problem was. I was apparently wrong about it working on the other branch; for whatever reason it would work if the anonymous user already had some saved collections (what the cookies are used for), and I'm still not sure why that is, but the following ended up resolving the issue:
#app.after_request
def set_cookie(response):
if not request.cookies.get(g.cookie_session.cookie_name):
response.set_cookie(g.cookie_session.cookie_name, g.cookie_session.cookie)
return response
The main things I needed to do were import "request" from flask and realize that I could reference the cookie and cookie name through just referring to the anonymous user ("cookie_session") class where they were set.
I have a view to create new users in my django project.
I am applying the #sensitive_post_parameters decorator to that view to make sure the password isn't logged if there is an unhandled exception or something like that (as indicated in the comments in the source code https://docs.djangoproject.com/en/2.0/_modules/django/views/decorators/debug/).
When I proceed to test the view, I would like to make sure that this protection of the sensitive information is still in place (that I didn't delete the decorator to the function by mistake or something).
I am aware, since the decorator is applied to my function, I can't test it directly from the view tests.
But, for example, with the #login_required decorator, I can test its effects with assertRedirects (as explained here How to test if a view is decorated with "login_required" (Django)).
I have been searching for a way to do that, but I can't find one that works.
I thought of something like this:
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)
but that gives me an
AttributeError: 'WSGIRequest' object has no attribute 'sensitive_post_parameters'
Any help would be appreciated.
Even it is telling me I shouldn't be attempting to test this, though I would really like to, as it is seems like an important behaviour that I should make sure remains in my code as it is later modified.
You have created a request using RequestFactory, but you have not actually used it. To test the effect of your view you need to import the view and call it.
from myapp.views import create_user
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
response = create_user(request)
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)
def frontblog(request):
if request.method=='POST':
for post in Posts.objects(tags=request.POST('search')):
posttitle=post.post_title
postcont=post.post_content
postdate=post.post_date
posttag=post.post_tags
return render_to_response("frontblog.html",
RequestContext(request,
{'post':post}))
I have tried to send the data from mongo db database as by search using tag post get retrieved and should be send to display on html page.
NB : answer based on badly indented code, so it's a bit of a guessing game... but if you want a correct answer learn to post correctly indented code.
You start your code with a test on request.method=='POST' and everything else is under that branch, which means that if it's a GET request (or PUT or whatever) your view function implicitely returns None.
There are quite a few other WTFs in your code but fix this one first. BTW a "search" should be done as GET request, not POST. Also, in a POST request, request.GET will most probably be empty. Finally, you DO want to use a Form to sanitize user inputs... Well, unless you don't mind your site or app being hacked by the first script-kiddie, that is.
So I'm pretty new to Flask and I'm trying to make my mind around one thing. So, if I understand well when you write a function within a Flask app and you use the #app.route decorator in that function, it only runs when you hit that path/url.
I have a small oauth app written in Flask that goes through all the authorization flow and then it return the token.
My question is how do I get that token from the #decorated function? For example, lets say I have something like this:
#app.route(/token/)
def getToken(code): #code from the callback url.
#/Stuff to get the Token/
#/**********************/
return token
If I hit the (/token/) url-path the function returns the token. But now I need to get that token and use it in another function to write and read from the API I just got the token from. My initial thought was doing this:
token = getToken(code)
But if I do that, I get this error:
RuntimeError: working outside of request context
So again, my question is, how do I get the token so I can pass it as a parameter to other functions.
Extract the token generation code into a separate function, so that you can call it from anywhere, including the view function. It's a good practice to keep the application logic away from the view, and it also helps with unit testing.
I assume your route includes a placeholder for code, which you skipped:
def generateToken(code):
#/Stuff to get the Token/
#/**********************/
return token
#app.route('/token/<string:code>')
def getToken(code):
return generateToken(code)
Just keep in mind that generateToken shouldn't depend on the request object. If you need any request data (e.g. HTTP header), you should pass it explicitly in arguments. Otherwise you will get the "working outside of request context" exception you mentioned.
It is possible to call request-dependent views directly, but you need to mock the request object, which is a bit tricky. Read the request context documentation to learn more.
not sure what the context is. You could just call the method.
from yourmodule import get_token
def yourmethod():
token = get_token()
Otherwise, you could use the requests library in order to retrieve the data from the route
>>> import requests
>>> response = requests.get('www.yoursite.com/yourroute/')
>>> print response.text
If you're looking for unittests, Flask comes with a mock client
def test_get_token():
resp = self.app.get('/yourroute')
# do something with resp.data
I want to use Tastypie authorization to give users access to only their objects. However, I am having problems understanding if I am doing it correctly. I followed the example here:
http://django-tastypie.readthedocs.org/en/latest/authorization.html#implementing-your-own-authorization
When I try to create a new object, I get a 404 error because there are problems evaluating
def create_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
Everything works if I comment that out. I thought commenting those two lines out would allow the user to create objects for other users, but when I tried it, I correctly get a 401 (UNAUTHORIZED) response.
Does that mean those two lines are unnecessary? How is Tastypie able to correctly determine if I am authorized to create objects?
When I was running this, I sent a POST request with 'user' equal to the appropriate URI (something like '/api/v1/user/1/'). I'm not sure if Tastypie is having problems determining
bundle.obj.user
when I do it that way.
Is it safe to just leave those two lines commented out? Is Tastypie authorizing the user with one of the other methods?
try:
def create_detail(self, object_list, bundle):
return bundle.obj == bundle.request.user
It looks like bundle.obj isn't populated during the create_detail authorization.
Also, create_detail for a user really doesn't make much sense, because there's no object for the user to own until its created anyways. You could just check if bundle.request.user is a valid user with permissions on the model.
In my case, I needed to check if the created object referenced an object owned by the user, so here's what I came up with:
def create_detail(self, object_list, bundle):
resource=BookResource()
book=resource.get_via_uri(bundle.data["book"], bundle.request)
return book.user == bundle.request.user
Anyways, bottom line: tastypie's docs are a little off.
And, I hope this helps.