How to display two forms on the same page? I will be grateful for your help
This is my views.py:
def register_user(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username=form.cleaned_data['username'], email=form.cleaned_data['email'], password=form.cleaned_data['password'])
user.save()
user_profil = UserProfil(user=user, name=form.cleaned_data['name'], last_name=form.cleaned_data['last_name'],city=form.cleaned_data['city'])
user_profil.save()
return HttpResponseRedirect('/profile/')
return render_to_response('access.html', {'formRegister':form}, context_instance=RequestContext(request))
else:
form = RegistrationForm()
return render_to_response('access.html', {'formRegister':form}, context_instance=RequestContext(request))
def login_user(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = LoginForm(request.POST)
if forml.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user_profil = authenticate(username= username, password=password)
if user_profil is not None:
login(request, user_profil)
return HttpResponseRedirect('/profile/')
else:
return HttpResponseRedirect('/login/')
return render_to_response('access.html', {'formLogin':form}, context_instance=RequestContext(request))
else:
form = LoginForm()
context = {'formLogin':form}
return render_to_response('access.html', context, context_instance=RequestContext(request))
This is my urls.py
url(r'^access/$','users.views.register_user'),
url(r'^access/$','users.views.login_user'),
access.html:
<form action="" method="post">{%csrf_token%}
{{ formRegister.as_p }}
<p><input type="submit" value="Rejestruj"/></p>
</form>
<hr>
<form action="" method="post">{%csrf_token%}
{{ formLogin.as_p }}
<input type="submit" value="Login"/>
</form>
There is one template(access.html) and two views
When I replace urls.py(order):
url(r'^access/$','users.views.login_user'),
url(r'^access/$','users.views.register_user'),
Display only loginform
What if you change the names of your form variable in the return statement i.e.
{'formRegister':form}
and the other one:
{'formLogin':form}
UPDATE:
In your url file, you could do the following:
url(r'^access/login/$','users.views.login_user'),
url(r'^access/register/$','users.views.register_user'),
The same template will still be used, but with different views to handle the forms.
Other alternatives include:
Putting different URLs in the action attribute of the two forms. Then you will have two different view functions to deal with the two different forms.
Reading the values of submit buttons from the POST data. You can tell which submit button was clicked, then handle the logic.
Related
i have a form, and i want to pass the user to it to see which logged in user filled it.
this is my forms.py
from .models import UserInfo
from django import forms
class InfoForm(forms.ModelForm):
class Meta:
model = UserInfo
fields = ('name', 'age', 'male', 'female', 'height', 'weight',
'BMI', 'BFP', 'phone', 'r_g_weight', 'physical_ready', 'fitness',
'workour_sports', 'others', 'goal_expression', 'body_change',
'noob','low_pro','semi_pro','pro','motivation_level','goal_block',
'change_time','past_sports','injury','work','work_time','wakeup_time',
'work_start_time','sleep_time','daily','hard_to_wake','ready_to_work',
'life_situation','weight_feel','daily_jobs','health_ready','workout_period',
'what_sport','where_sport','home_sport','weekly_time','sport_dislike','daily_food',
'food_quantity','hunger','vitamins','rejims','vegetables','goal_rec',
'stop','rec','heart','chest','chest_month','dizzy','bones','blood','other_reason')
and this is my view, i asked for the user with request.user , but the field in db always is empty for username.
def userForm(request):
if request.method == "POST":
form = InfoForm(request.POST)
if form.is_valid():
form.user = request.user
form.save()
return redirect('profile')
else:
form = InfoForm()
context = {
'form':form
}
return render(request, 'fitness/user_form.html', context)
so i have user in my models which has foreign key to my account
user = models.ForeignKey(Account,on_delete=models.CASCADE, null=True, blank=True)
and this is my template:
<div class="container">
<form action="{% url 'user-form' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="submit">
</form>
</div>
The problem lies in the way you are saving your form. You set the user attribute on the form, instead of the actual model object. The following should fix your issue
def userForm(request):
if request.method == "POST":
form = InfoForm(request.POST)
if form.is_valid():
# dont commit the object to the database as we need to set the user
object = form.save(commit=False)
# set the user
object.user = request.user
# finally save the object now that the user has been set
object.save()
return redirect('profile')
else:
form = InfoForm()
context = {
'form':form
}
return render(request, 'fitness/user_form.html', context)
My redirect for my login page is not working correctly when I submit a form.
def login_page(request):
form = LoginForm(request.POST or None)
context = {
'form': form,
}
print(request.user.is_authenticated)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = authenticate(request, username=username, password=password)
if user is not None:
print(request.user.is_authenticated)
login(request, user)
# Redirect to a success page.
return redirect("login")
else:
# Return an 'invalid login' error message.
print("Error")
return render(request, "content/login.html", context)
I am expecting it to redirect to same page and print an output that lets me know the authentication worked. But this is what actually happens..
Page not found(404)
Request Method: GET
Request URL:http://127.0.0.1:8000/login/POST?username=stone&password=pass
Any idea as to what is going on?
You haven't shown your template, but it looks like you have action="POST" instead of method="POST" in your form tag.
Be sure, that your template.html looks like this:
<form method="post">
{% csrf_token %}
{{ form }}
</form>
def login_user(request):
if request.user.is_authenticated():
return redirect(reverse('homepage'))
form = LoginForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
user = authenticate(username=form.cleaned_data['email'], password=form.cleaned_data['password'])
if user is not None:
login(request, user)
return redirect(reverse('homepage'))
else:
error_message = "* Password you entered is incorrect."
return render(request, "account/login.html",{
"form": form,
"error_message": error_message,
})
else:
return render(request, "account/login.html", {
"form": form,
})
When a user accesses a url which requires login. The view decorator redirects to the login page. after the user enters his username and password how can I redirect the user to the page he was trying to access ('next') ?
Views.py
def login_view(request):
template = 'pos/login.html'
form = LoginForm
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
messages.success(request, "You have logged in!")
return redirect('home')
else:
messages.warning(request, "Your account is disabled!")
return redirect('/login')
else:
messages.warning(request, "The username or password are not valid!")
return redirect('/login')
context = {'form': form}
return render(request, template, context)
#login_required(redirect_field_name='next', login_url='/login')
def bar(request):
template = 'pos/bar.html'
drink = OrderItem.objects.filter(product__catgory__gt=1).order_by('-created')
context = {'drink': drink}
return render(request, template, context)
Login.html
<form action="/login" id="login_form" method="post" class="form-signin">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-lg btn-primary btn-block" type="submit" value="login">Sign in</button>
<input type="hidden" name="next" value="{{next}}" />
</form>
url.py
url(r'^login', views.login_view, name='login'),
forms.py
class LoginForm(AuthenticationForm):
username = forms.CharField(label="Username", required=True, max_length=30,
widget=forms.TextInput(attrs={
'class': 'form-control',
'name': 'username'}))
password = forms.CharField(label="Password", required=True, max_length=30,
widget=forms.PasswordInput(attrs={
'class': 'form-control',
'name': 'password'}))
You can try:
return redirect(self.request.GET.get('next'))
The accepted answer does not check for the next parameter redirecting to an external site. For many applications that would be a security issue. Django has that functionality inbuilt in form of the django.utils.http.is_safe_url function. It can be used like this:
from django.shortcuts import redirect
from django.utils.http import url_has_allowed_host_and_scheme
from django.conf import settings
def redirect_after_login(request):
nxt = request.GET.get("next", None)
if nxt is None:
return redirect(settings.LOGIN_REDIRECT_URL)
elif not url_has_allowed_host_and_scheme(
url=nxt,
allowed_hosts={request.get_host()},
require_https=request.is_secure()):
return redirect(settings.LOGIN_REDIRECT_URL)
else:
return redirect(nxt)
def my_login_view(request):
# TODO: Check if its ok to login.
# Then either safely redirect og go to default startpage.
return redirect_after_login(request)
You can try by simply add this input field before submit button in accounts/login.html template
<input type="hidden" name="next" value="{{ request.GET.next }}"/>
Passing next to the login form and then the form passing that value on to view in a hidden input can be a bit convoluted.
As an alternative, it's possible to use django.core.cache here.
This way there is no need to pass anything extra to the form or to give the form an extra input field.
def login_view(request):
if request.method == 'GET':
cache.set('next', request.GET.get('next', None))
if request.method == 'POST':
# do your checks here
login(request, user)
next_url = cache.get('next')
if next_url:
cache.delete('next')
return HttpResponseRedirect(next_url)
return render(request, 'account/login.html')
This actually works for me quite nice:
from django.shortcuts import redirect
def login(request):
nxt = request.GET.get("next", None)
url = '/admin/login/'
if nxt is not None:
url += '?next=' + nxt
return redirect(url)
If previous URL contained next - call "login" URL and append the previous "next" to it.
Then, when you logged in - you'll continue with the page that was previously intended to be next.
In my project I made the following helper which works for Swagger login/logout:
def _redirect(request, url):
nxt = request.GET.get("next", None)
if nxt is not None:
url += '?next=' + nxt
return redirect(url)
def login(request):
return _redirect(request, '/admin/login/')
def logout(request):
return _redirect(request, '/admin/logout/')
Yes Arun Ghosh option is better but it leads to an exception in cases where there is no next value is found.
Hence I used this approach.
try: return redirect(request.GET.get('next')) except TypeError: return HttpResponseRedirect(reverse("default_app:url_name"))
OR
except Exception as e: return HttpResponseRedirect(reverse("default_app:url_name"))
path_redirect = request.get_full_path().split('?next=',1)
if '?next=' in request.get_full_path():# Redirecting After Login
return redirect(path_redirect[1])
else:
return redirect('index')
I have tried to use modelformset_factory(User) to create a form to add (and in next step edit) a user.
I'm confused, why it creates a form with my current user and an empty one for a new one?
Any Idea how i could remove the one with the current?
Here is my view.py code:
#login_required
def update_or_edit_user_profile(request, UserID = None, template_name='userprofile_form.html'):
#check when a userid is provided if its the personal or if the user is allowed to edit the profile
if UserID != None:
if (request.user.has_perm('change_user_profile') or request.user.pk == UserID):
pass
else:
raise PermissionDenied
# when user is allowed to continue:
UserFormSet = modelformset_factory(User)
if request.method == 'POST':
userformset = UserFormSet(request.POST, request.FILES)
if userformset.is_valid():
newUser=userformset.save()
else:
userformset = UserFormSet()
return render_to_response(template_name, {
"userformset": userformset,
})
and my template:
<form action="" method="post">{% csrf_token %}
{{ userformset.as_p }}
<input type="submit" value="Send message" />
</form>
You're confusing forms with formsets. A formset is a collection of forms, so Django is giving you exactly what you asked for. If you only want a single form, then that's what you should use:
class UserForm(forms.ModelForm):
class Meta:
model = User
def update_or_edit_user_profile...
user = User.objects.get(pk=UserID)
if request.method == 'POST':
form = UserForm(request.POST, instance=user)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = UserForm(instance=User)
return render(request, template_name, {'form': form})
I have a form where I must enter e-mail, but in the template do not have space for input, only after passing the validation window appears with the introduction e-mail.
At this moment I see only send button.
This is my code:
<div class="col-lg-6">
<form action="./" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="send">
</form>
</div>
model.py
class InputEmail(models.Model):
email = models.EmailField()
def __unicode__(self):
return self.email
forms.py
from models import InputEmail
from django import forms
class EmailForm(forms.ModelForm):
class Meta:
model = InputEmail
fields = ('email',)
views.py
class Home(View):
template_name = 'index.html'
def get(self, request):
return render(request, self.template_name)
def post(self, request):
if request.method == 'POST':
form = EmailForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "You send e-mail to us!")
return HttpResponseRedirect('./')
else:
form = EmailForm()
return render(request, 'index.html', {
'form': form
})
The rest - writing and reading from the database works fine.
How enter the input and give it a style?
well the problem is that the first time you arrive to the view the get method is being called (and it is okay, since this is a GET request).
But, inside that get method you are not sending your form to the template. So it can't be rendered.
instead, your get method should look like that:
def get(self, request):
form = EmailForm()
return render(request, self.template_name, {"form": form})
note that the condition in the post method is redundant. You have an "else" but you never get there since the post method is only called when it is a POST request.
Meaning your post method should look like this:
def post(self, request):
form = EmailForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('./')
return render(request, self.template_name, {
'form': form
})