I am trying to implement a page using Django where the user is able to create content, hit submit, and then is prompted to register or login if they are not currently logged-in. One of the fields in the model for the content references the user, so they must be logged-in to create it, however I want them to be able to input all of the data before they are prompted with logging-in. I have used the #loginrequired decorator on the view, but that forced the user to be logged-in before they create the content. Here is the view currently:
def search(request):
form = LocationInput()
if request.method == "POST":
form = LocationInput(request.POST)
if form.is_valid():
t = Trip(trip_name = form.cleaned_data['city'])
t.user = request.user
t.save()
form.save()
l = Location.objects.get(google_id=form.cleaned_data['google_id'])
l.trips.add(t)
l.save()
return HttpResponseRedirect('/trips/')
return render(request, 'frontpage/search.html', {'form': form})
It loads the form, creates an object that needs a user associated with it so I need to register the user but keep the data from LocationInput(request.POST) until after the user has registered. Any help would be greatly appreciated!
I can see two options:
Allow NULL for user reference, save the content in a state "pending user login or sign up", and store the ID of the content object in a session. Vacuum "old" contents with no user reference on a regular basis.
Save the whole data of the form in a session.
I like the first one better since you, as a superuser, have access to the content even if the user didn't login or signup, and if the user contact you later telling you he had troubles signing in, you will be able to help and recover the content he submitted. While if everything is stored in session, once the session is deleted, it's all lost.
Related
This is probably a simple answer but I cant figure it out. I have a comment system on my blog. I need to get the username from the user id.
I get the id from which is a fk to the users table
{{child_comment.parent_userdata_id}}
Usually when I need to do this I just user .username but it doesn't seem to work in this case
The only way you can get object data from the database is to fetch it on the server-side.
Unfortunately, you can't do that on the live HTML template.
Django template is just for evaluating the pre-existing context data for better use.
So, filtering the username from user id in views (backend) and passing it via the context into the template is the only (and probably the best) option.
Assuming user login is required to comment, you can create a variable of user = request.user in your view function, now user variable has the instance of user and pass it as context in template. It would look like this
views.py
def view_function(request):
user = request.user
# do something
context = {
'user' : user,
}
return render(request, 'template.html', context)
template.html
<p>{{user.username}}</p>
reference
I'd like to generate a random 1-time passcode for a user that appears as a disabled field in a Django form.
The passcode will be shown in the form to the user on the page, and the user will not be able to edit it, but it will be submitted with the form. I do not want my users to set their own passcodes, but I want to tell them what their passcode is.
What is the best way to ensure that the 1-time passcode that is generated for users is not edited by users? I have been using session variables to remember the value so that I can confirm it has not been tampered with upon submit.
def my_page(request):
# If submitted
if request.method == "POST":
# Check to make sure passcode wasn't altered
if (request.POST.get('passcode') == request.session['pw']):
... rest of function here ...
# Generate passcode and store it the session
request.session['pw'] = genRandomPassword()
# Init the form with a passcode
form = MyForm(initial={'passcode': request.session['pw']})
return render(request, 'example.html', {'form': form})
Is there a better method for accomplishing what I am attempting to do? I think what I am doing works, as long as users can't edit their session variables. It does break if a user opens up another tab, as then a second passcode session variable will be generated.
I do not want to store the passcodes in a database.
I think instead of checking request.POST.get('passcode') == request.session['pw'] simply ignore the data inside POST and use data from session so even a user somehow changes the password you won't care about it (note that you don't even need to add pw to the form, it can be a template context variable)
Note: I personally think your solution is not a good idea, do not generate a password before submit, let the user fill the form and after successful submit generate their random password, after submitting show a page to user saying your form was submitted and your password is blah blah
Note 2: problem with your solution is assume I open a page and my generated password is 1 then I open a new tab and my generated password is 2, (and now 2 is stored in session as pw) I go and fill the form on the first page and submit it. what happens now? with your sample code you have to show an error to user, but user didn't to anything wrong, and with my fix (first paragraph) user thinks her password is 1 but it's actually 2
The current flow for visitors with django-allauth is if the visitor fills in a form, if they are not already authenticated they are shown a login modal with option of facebook login or standard signup form, with the original form data being saved in ACCOUNT_SIGNUP_FORM_CLASS=SignupForm
class SignupForm(forms.Form):
def signup(self, request, user):
new_user = Profile()
new_user.user = user
new_user.save()
# if form data provided with signup save it.
model = self.cleaned_data['model']
if model:
# save the form
This works fine if the user signs up using the standard signup form, but if they signup using facebook social account the values from the form are now empty strings i.e. self.cleaned_data['model']. I assume the original request object is destoryed so the post data is lost? There also doesn't seem anyway to pass the form data to facebook and receive it back e.g.
<a title="{{provider.name}}" href="{% provider_login_url provider.id modal="1" process="login" next=request.path scope=scope auth_params=auth_params %}"
Is the only way to do what I want is to save the form data using local storage or the database then somehow assign it back to the visitor once registered and save it?
What I've gone with is changing the Facebook signup button to link to an intermediate view where I save the form data as session data and then redirect back to the allauth facebook login url.
I then extract the form data from the session in the signup method after the user has authenticated with facebook.
I've posted about this problem before, but I still haven't found a solution so I'm hoping I'll have better luck this time.
I have a form that takes inputted data by the user. In another page, I am creating the identical form that the user has populated (pre-filled with that information) for editing purposes. Users will come to this page to EDIT the information they have already put in. My problem is that it isn't overwriting the instance.
def edit(request):
a = request.session.get('a', None)
if a is None:
raise Http404('a was not found')
if request.method == 'POST':
form = Name_Form(request.POST, instance=a)
if form.is_valid():
j = form.save( commit=False )
j.save()
else:
form = Name_Form( instance = a )
For this form, I'm using "unique_together" for some of the values. I'm also calling on `{{ form.non_field_errors }} in the template.
What is happening is when I make changes in the editing view, if the fields changes involves those defined in "unique_together" then an error is returned telling me that the instance already exists. Otherwise it saves a new instance. It isn't OVERWRITING.
Note that the reason i am using unique_together is that I want to prevent users from initially inputting the same form twice (before the editing stage, in the initial inputting view).
Any ideas?
EDIT: note that "a" refers to a session that includes a drop down box of all the available instances. This carried forward will indicate which instance the user wants to edit.
`
Why not do a database lookup of the model your trying to save and pull the fields from the form to the model then save the model?
Instead to store model a in session you should store it on database. Then edit it:
def edit(request, pk):
a = A.objects.get( pk = pk)
...
pk it the a identifier, you can send it to view via urls.py. I encourage to you to use POST/Redirect/GET pattern.
You can add a 'state' field on your model to control workflow (draft, valid)
You should not save objects in the session. If you really need to use a session - save a PK there and retrieve object right before giving it to Form. But the better solution is to send it in GET or POST parameters or included in url. Sessions are unreliable, data inside it can be destroyed between user's requests.
And you can retrieve value from a session in a more pythonic way:
try:
a = request.session['a']
except KeyError:
raise Http404('a was not found')
This is something I've wondered about in a couple of frameworks that I've messed around with. Assuming I don't want to automatically log a user in when they register (I want them to activate) how can I make it so a user can't just visit the "register-success" page? Right now, here's what I have:
def register(request):
if request.method == 'POST':
rf = forms.RegisterForm(request.POST)#register form
pf = forms.ProfileForm(request.POST)#profile form (additional info)
lf = forms.LoginForm()#login form is also on this page but is empty when registering
if rf.is_valid() and pf.is_valid():
newuser = User(username=rf.cleaned_data['username'],email=rf.cleaned_data['email'])
newuser.set_password(rf.cleaned_data['password'])
newuser.save()
#need to mark newuser as inactive still
profile = pf.save(commit=False)
profile.user = newuser
profile.save()
return HttpResponseRedirect("/register-success/")
return render_to_response("authentication/index.html", {'rform': rf, 'pform':pf,'lform':lf})
return main(request)
def register_success(request):
return render_to_response("authentication/register-success.html")
My url-conf:
(r'^register-success/$','register_success'),
The other way I thought to do it was to just render_to_response("authentication/register-success.html") and not do the redirect. The benefit is, no one can access the register-success.html page, the downside is if the user refreshes the page it will try and resubmit the POST. What's the best practice?
I would stick with the redirect, getting duplicate users is a fairly large risk. What is the risk of someone seeing your register success page who hasn't registered? If there is a risk, you could always generate a random token, put it in session and pass it to your register-success page and then in your view check that the token matches. But that seems like a lot of work for what typical success pages are.
My recommendation would be to not worry about people being able to get to that page without registering. If it is just static HTML, there can't be any risk with showing to to everybody, right?
You can set the cookie, a session key in register view that you can check for in the register_success view only on its presence render the page, else redirect to main register.