All,
I am having a field day with page refetching. Any help or pointer will be greatly appreciated!! The behavior is a bit specific to mobile browser.
Problem:
I have two pages and created a shortcut link to pg#1 on the home screen. Through a form submit button, user is taken from pg#1 to pg#2. All that is working fine.
Now once I am on pg#2. I will leave the browser and click the shortcut later. The browser will stay on pg#2 and won't go to pg#1 even though the path in URLS is different between the two views.
Update#1:
Here is the code snippets.
def sendmsg(request):
if request.method =='POST':
messages.add_message(request, messages.INFO, "Hello world")
return redirect ('rcvmsg')
return render_to_response('sendMsg.html',RequestContext(request))
def rcvmsg(request):
'''view that receives the msg.'''
printMsg ='Didnt get a message'
if messages:
thisMsg = messages.get_messages(request)
for rcvMsg in thisMsg:
printMsg = rcvMsg
return render_to_response('rcvMsg.html',{'print_msg':printMsg},RequestContext(request))
URL:
url(r'^rcvMsg/','mydomain.mainApp.views.rcvmsg',name='rcvmsg'),
(r'^sendMsg/code','mydomain.mainApp.views.sendmsg'),
It is almost like Django decides that since I have already visited view#1, it doesn't need to fetch it again. This problem or behavior doesn't happen if I move the same code that handle the two views and the templates to a bare bone test project.
Setup:
I am using django-registration, context session. I am not using any HTML caching tag.
I already have DEBUG turned on in my settings.py. Are there other ways that I can tell what the server is doing.
Thanks in advance.
pdxMobile
Found out what the problem was. I have the form action set back to the view itself in my template. I guess the browser thinks that since the action is back to the same page and so a reload is unnecessary.
Before:
<form action="." method="post">
{% csrf_token %}
Fix:
<form action="./next" method="post"> <--the "next" is fictitious & doesn't exist in URL-->
{% csrf_token %}
Hope this useful for someone someday.
Cheers. -P
Related
my code is simple but I admit I have taken it from the internet.
I want to update a model with a button click. Which model, it is chosen by the variable. So I have this html code:
<form action="{% url 'reception:update_status' slug=name %}" method="POST">
{% csrf_token %}
<input type="submit" value="has arrived">
</form>
This code is in url.py
re_path('update_status/(?P<slug>[-a-zA-Z0-9_]+)$', views.update_status, name='update_status'),
and in views.py
def update_status(request, slug):
if request.method == 'POST':
p = MyModel.objects.filter(name=slug)
p.status = 'is waiting'
p.update()
return redirect(request, 'home')
Now with the code like this it comes back with the following error when I click on the button!
Reverse for '<WSGIRequest: POST '/update_status/Name10'>' not found. '<WSGIRequest: POST '/update_status/Name10'>' is not a valid view function or pattern name.
and I have no clue what this means. Please help?
Thanks
For regex patterns in Django 2.0, you need to use re_path, instead of path for your url.
I solved this problem with pk rather than slugs.
I would recommend everyone who is new to Django to create an id field for every Model. Because that can then be used to pass parameters very easy. Slug is more complicated and makes life unnecessarily difficult!
I am trying to make a button redirect the user to a new url after they submit a form. This is how it is right now, and it works properly and all the data gets sent to the django database.
<form method='POST' action='' class="col-md-6 col-md-offset-7" style="background-color: lightgreen; border-radius: 10px">
However, when I change the action to
action="{% url 'ridesharing:request-success' %}",
the redirect works, but the data does not go to my django database.
What is going on here?
You seem to have some confusion here. The action of the form is where the browser will send the data. Obviously, if you don't point that at the view which actually processes the data, then it won't be saved.
To redirect after a post, your view should return a redirect.
When you declare a form with an empty action attribute:
<form method='POST' action=''>
the POST data will be sent to the same URL. This is useful because if there is some error in the form, it's easy to re-display it with all fields filled with values entered by the user. Then, when the form becomes valid, a redirect is done to the confirmation page.
When you declare your form that way:
<form method='POST' action='{% url 'ridesharing:request-success' %}'>
The data entered by the user in the form will be sent to the view request-success. But this view probably only render the template of the confirmation page. If you want to correctly handle data from the form, you have to set action attribute of your <form> to the same view, or easier, keep it empty.
I do not understand why Daniel Roseman's post isnt accepted as the answer. It helped me when I wanted to redirect a create form to its update form.
Basically in the view of the app I defined the get_success_url to reverse_lazy to the data-update.
def get_success_url(self):
return reverse_lazy('app_name:data-update')
Just replace the 'app_name:data-update' with the appropriate url.
I'm trying to build a simple website with login functionality very similar to the one here on SO.
The user should be able to browse the site as an anonymous user and there will be a login link on every page. When clicking on the login link the user will be taken to the login form. After a successful login the user should be taken back to the page from where he clicked the login link in the first place.
I'm guessing that I have to somehow pass the url of the current page to the view that handles the login form but I can't really get it to work.
EDIT:
I figured it out. I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
EDIT 2:
My explanation did not seem to be clear so as requested here is my code:
Lets say we are on a page foo.html and we are not logged in. Now we would like to have a link on foo.html that links to login.html. There we can login and are then redirected back to foo.html.
The link on foo.html looks like this:
<a href='/login/?next={{ request.path }}'>Login</a>
Now I wrote a custom login view that looks somewhat like this:
def login_view(request):
redirect_to = request.REQUEST.get('next', '')
if request.method=='POST':
#create login form...
if valid login credentials have been entered:
return HttpResponseRedirect(redirect_to)
#...
return render_to_response('login.html', locals())
And the important line in login.html:
<form method="post" action="./?next={{ redirect_to }}">
So yeah thats pretty much it, hope that makes it clear.
You do not need to make an extra view for this, the functionality is already built in.
First each page with a login link needs to know the current path, and the easiest way is to add the request context preprosessor to settings.py (the 4 first are default), then the request object will be available in each request:
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
)
Then add in the template you want the Login link:
base.html:
Login
This will add a GET argument to the login page that points back to the current page.
The login template can then be as simple as this:
registration/login.html:
{% block content %}
<form method="post" action="">
{{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
To support full urls with param/values you'd need:
?next={{ request.get_full_path|urlencode }}
instead of just:
?next={{ request.path }}
This may not be a "best practice", but I've successfully used this before:
return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Django's built-in authentication works the way you want.
Their login pages include a next query string which is the page to return to after login.
Look at http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required
I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
I encountered the same problem. This solution allows me to keep using the generic login view:
urlpatterns += patterns('django.views.generic.simple',
(r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
In registration/login.html (nested within templates folder) if you insert the following line, the page will render like Django's original admin login page:
{% include "admin/login.html" %}
Note: The file should contain above lines only.
See django docs for views.login(), you supply a 'next' value (as a hidden field) on the input form to redirect to after a successful login.
You can also do this
<input type="hidden" name="text" value="{% url 'dashboard' %}" />
i cant quite find it so i hope someone can help me out.
I found the option of using the
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth" )
In django (1.5). But now its not clear for me how i should use it. Should i still put the request in my views, or can i with this enabled use the user_object in my template without sending an extra variably with the Requestcontect
For example:
My view at the moment:
def user_characters(request, user_id):
characters = Character.objects.filter(user=user_id)
user = User.objects.get(id=user_id)
return render_to_response('characters.html',
{'characters': characters, "user": user},
context_instance=RequestContext(request))
My template:
{% extends "base.html" %}
{% block mainframe %}
{% if characters|length < 3 %}
<p>New Character(WN)</p>
{% endif %}
And then the rest of my view.
I notice in almost every view i make i want the user_object send with it.
Can someone please give me an example of how this works?
With kind regards
Hans
django.contrib.auth.context_processors.auth context processor is enabled by default, you don't have to add anything. When you use RequestContext(), a context variable user is available in all templates that you can use. To get id {{userd.id}}.
To check user is authenticated or not, do
{% if user.is_authenticated %}
{# handle authenticated user #}
{%else%}
{# handle anonymous non-authenticated users #}
{%endif%}
You should not expose the user id in the url, you wont need it anyway, if you use django sessions- and the authentication framework. You can always check the logged in user via request.user in your serverside view. With the context processor your should be able to access the user with user.desiredattribute, but you should not need it for the url you try to create.
The docs on this seem pretty clear to me:
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext
If you want context processors to function, you must ensure that you're using a RequestContext instance. You can do that by explicitly creating it in your views, as you show, or (more conveniently, in my opinion) by using the render shortcut rather than render_to_response as documented here:
https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render
With the django.contrib.auth.context_processors.auth context processor in place, the user will always be available in the context variable user. At least, assuming your template is being rendered with a RequestContext instance.
You absolutely should not trust a variable obtained from the URL to determine the user if you have any kind of controlled information. With the system you have shown, anyone can view anyone's data simply by editing the URL. That might be OK for a totally insecure application, but it's much more normal to look at request.user.
When I submit the form (eg: below), url gets redirected to localhost:8000/test/result/, and I get some result. This step works fine.
However, when I click on browser back button to go back to the initial form, Firefox doesn't load the form, although url has changed to localhost:8000/test/. I get a blank page. Also, if I click the back button again, it takes me to localhost:8000 page. Chrome and IE works though.
What am I doing wrong and how can I fix this FF issue?
Many thanks in advance.
#---test.html---
<form id="input-form" action="{% url test.views.main_view %}" method="post" enctype="multipart/form-data">{% csrf_token %}
...
</form>
#---views.py---
class MainView(FormView):
template_name = 'test.html'
form_class = UserInputForm
success_url = 'result/'
def form_valid(self, form):
...
#---urls.py---
urlpatterns = patterns('test.views',
url(r'^$', view='main_view', name='main-view'),
url(r'^result/$', view='result_view', name='result-view'),
)
I have a feeling this is the issue. Failing that, something that will definitely work is setting your Cache-Control header to “no-cache, must-revalidate, no-store” – but that's a nasty brute force solution.