Confirm Form Resubmission with Context Required Django - django

I have an account page that lets users edit their accounts. When the save button is pressed, I run the following code:
request.user.first_name = request.POST['first_name']
request.user.last_name = request.POST['last_name']
request.user.save()
context['alert'] = {
'title': "Your information has been updated",
'color': 'primary',
}
As you can see, I pass in context that, in my template, renders as an alert. However, when I refresh the page, it says: Confirm Form Resubmission
How can I get rid of this error? Thanks!

A successful POST request normally results in a redirect, this is the so-called Post/Redirect/Get pattern [wiki].
In order to send messages to the user, you can make use of the messaging framework [Django-doc]. So you can add a message for a user, and then render it in the other view(s):
from django.shortcuts import redirect
from django.contrib import messages
def my_view(request):
request.user.first_name = request.POST['first_name']
request.user.last_name = request.POST['last_name']
request.user.save()
messages.success(request, 'Your information has been updated')
return redirect('name-of-some-view')

Related

Handling user registrations Using only Django without the need to be redirected to other template

This is my view
class UserRegistrationView(FormView):
template_name = "register/register_form.html"
form_class = None
extra_fields_form_page_slug = ""
email_template = "register/account_activation_email.html"
def get_form(self, form_class=None):
form = super().get_form(form_class)
add_extra_fields(
form.fields, form.helper.layout.fields, self.extra_fields_form_page_slug
)
return form
def get_extra_form(self):
return FormPage.objects.filter(slug=self.extra_fields_form_page_slug).first()
def form_valid(self, form):
user = form.save(commit=False)
user.is_active = False
user.save()
email = form.cleaned_data.get("email")
email_template = "register/account_activation_email.html"
send_confirmation_email(
self, "Activate Your Account", user, email, email_template
)
return render(self.request, "register/after_submission.html")
This is working fine (registration wise) but it's not from many other sides, because I have the registration form as a pop up window in the header, so it's available throughout the whole website, my problems are:
if the user had a successful registration they will be redirected to the specified template "after_submission" what I want is to stay on the same page and display a pop up with some message
if the user had an unsuccessful registration they will be redirected to the main template "register_form.html" with the errors displayed their, what I want is to stay on the same page and to display the error messages on the pop up form if the user opened it again
is this achievable using only Django?? or I must throw some JS in there, and if JS is the answer, can you give me a quick insight into how to do it?
You can redirect to the same page in your CBV :
from django.http import HttpResponseRedirect
return HttpResponseRedirect(self.request.path_info)
As stated in the comment your solution require Ajax and JS, you can however redirect to the same page but that will make a new request and refresh the whole page which might no be ideal for you.
There is a tutorial to work with Django and Ajax Ajax / Django Tutorial

Django How to Add Base Form Template Context Processer

In my navbar I have a newsletter button that pops up a modal. In the modal there is a form that I can use to get the email and do some form manipulation. Since this modal is in the base template, the form must be available for all urls. I have added 'blog.context_processors.email_form' in the settings, and a context_processer.py file with the below info:
from .forms import EmailForm
def email_form(request):
return {
'email_form': EmailForm()
}
In my forms.py I have:
from django import forms
from .models import Email
class EmailForm(forms.ModelForm):
email = forms.EmailField(label='',
widget=forms.EmailInput
(attrs={'id': 'emailInput', 'class': 'article-search',
'placeholder': 'Enter yorffreur email here...', 'type': 'text'}))
class Meta:
model = Email
fields = ['email']
def clean_email(self, *args, **kwargs):
email = self.cleaned_data.get('email')
qs = Email.objects.filter(email__iexact=email)
if qs.exists():
raise forms.ValidationError('This email already exists.')
return email
In the base templates I have included the form as {{ email_form }}. But I do not know where to add the form manipulation. Usually I add it in the views but I'm new so I am an unsure how to do this.
You can write a view wherever you want that will receive the form and validate it then redirect to a page that will confirm the success of the subscription.
You just have to use the action property of the <form> tag to specify which view will handle the form :
<form method="post" action="{% url 'handle_newsletter' %}">
Then in your view, something like this :
def handle_newsletter(request):
form = EmailForm(request.POST)
if form.is_valid():
form.save()
return redirect('subscription_confirmation') # you would need to create this view
# An error occurred
print(form.errors)
return redirect('home')
Don't forget to update your urls.py with the appropriate view names.

How To Make User Profile In Django?

How To Make User Profile in Django?
Hi I Want to Know How To Make User Profile when user signup in our django app i want create a profile page for the person
Here is my Views.py
def user_reg(request):
register = False
if request.method == 'POST':
form = user_register_form(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
register = True
if register == True:
return HttpResponseRedirect("/accounts/login")
else:
print(form.errors)
else:
form = user_register_form()
context = {'reg':form,}
return render(request,'signup.html',context)
Models.py
class user_register_model(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
join_date = models.DateTimeField(default=timezone.now)
I Want To Know How To Create Profile Page If User sign Up in our website Problem is How To Create His Profile Page
For Example:
If You Register on Stack overflow You Click on profile icon and you can go to your page
Stack overflow Make Your Page
I Need Some Thing Like That
When User Signup i need user page but how to make that?
i research on google and youtube i can't find any prefect answer
can you please help me?
Create a URL in urls.py like this:
path('profile/<username>', views.user_profile, name='user_profile'),
views.py (If you are using User model to save user data.)
def user_profile(request, username):
user = User.objects.get(username=username)
context = {
"user": user
}
return render(request, 'user_profile.html', context)
user_profile.html (use profile data as per requirement)
{{ user.username }}
{{ user.first_name }}
You can check this on link http://127.0.0.1:8000/profile/<username>/. replace username with user's username and page will show data of only that user.
-----------Edit-----------
If you want to create link, use this:
<a class="nav-link navaour" href="{% url 'profile' username=<username> %}">
replace user's username.
You can just create a view with a template see this. You can have editable forms or anything you like. This view will be shown only if the user is logged in and for unauthorized users redirect them to your login page.

password reset implementation with djoser

I wanted to use djoser for the reset password functionality and as per the documentation:
PASSWORD_RESET_CONFIRM_URL
URL to your frontend password reset page. It should contain {uid} and
{token} placeholders, e.g. #/password-reset/{uid}/{token}. You should
pass uid and token to reset password confirmation endpoint.
I have done the following:
PASSWORD_RESET_CONFIRM_URL': 'reset/password/reset/confirm/{uid}/{token}',
url
url(r'^reset/password/reset/confirm/(?P<uid>[\w-]+)/(?P<token>[\w-]+)/$', PasswordResetView.as_view(),),
View :
class PasswordResetView(APIView):
def get (self, request, uid, token):
post_data = {'uid': uid, 'token': token}
return Response(post_data)
In my mail I get this link : http://127.0.0.1:8000/reset/password/reset/confirm/Mjk/538-954dccbc1b06171eff4d
This is obvious that I will get :
{
"uid": "Mjk",
"token": "538-954dccbc1b06171eff4d"
}
as my output but I wanted to go to auth/password/reset/confirm when the user clicks the link in the mail.
Lets describe the actions first:
The user clicks on the link to reset the password. reset password
(Here you need a form to obtain a username or email address, depending on your settings) The user enters the username and clicks Submit.
The user receives an email with a link to reset the password.
The link opens the browser, which contains the form "Create a new password".
The user enters a new password and sends a form
The browser redirects the page to the home page and gives feedback that the password has been reset.
You can then use following method to reset the password.
#template
<p>Use the form below to change your password. Your password cannot be the same as your username.</p>
<form role="form" method="post">
{% csrf_token %}
<input type="password" name="password1" placeholder="New Password">
<input type="submit">
</form>
#view
from django.shortcuts import redirect, render
from djoser.conf import django_settings
def reset_user_password(request, uid, token):
if request.POST:
password = request.POST.get('password1')
payload = {'uid': uid, 'token': token, 'new_password': password}
url = '{0}://{1}{2}'.format(
django_settings.PROTOCOL, django_settings.DOMAIN, reverse('password_reset_confirm'))
response = requests.post(url, data=payload)
if response.status_code == 204:
# Give some feedback to the user. For instance:
# https://docs.djangoproject.com/en/2.2/ref/contrib/messages/
messages.success(request, 'Your password has been reset successfully!')
return redirect('home')
else:
return Response(response.json())
else:
return render(request, 'templates/reset_password.html')
It's always important to catch errors, handle redirects and add the default renderer classes. In my case, I ended up using the following.
#view
import requests
from django.contrib import messages
from django.contrib.sites.models import Site
from django.http import HttpResponseRedirect
from django.shortcuts import render
from rest_framework.decorators import (api_view, permission_classes,
renderer_classes)
from rest_framework.permissions import AllowAny
from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
#api_view(('GET', 'POST'))
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
#permission_classes([AllowAny])
def reset_user_password(request, **kwargs):
# uses djoser to reset password
if request.POST:
current_site = Site.objects.get_current()
#names of the inputs in the password reset form
password = request.POST.get('new_password')
password_confirmation = request.POST.get('password_confirm')
#data to accept. the uid and token is obtained as keyword arguments in the url
payload = {
'uid': kwargs.get('uid'),
'token': kwargs.get('token'),
'new_password': password,
're_new_password': password_confirmation
}
djoser_password_reset_url = 'api/v1/auth/users/reset_password_confirm/'
protocol = 'https'
headers = {'content-Type': 'application/json'}
if bool(request) and not request.is_secure():
protocol = 'http'
url = '{0}://{1}/{2}'.format(protocol, current_site,
djoser_password_reset_url)
response = requests.post(url,
data=json.dumps(payload),
headers=headers)
if response.status_code == 204:
# Give some feedback to the user.
messages.success(request,
'Your password has been reset successfully!')
return HttpResponseRedirect('/')
else:
response_object = response.json()
response_object_keys = response_object.keys()
#catch any errors
for key in response_object_keys:
decoded_string = response_object.get(key)[0].replace("'", "\'")
messages.error(request, f'{decoded_string}')
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
# if the request method is a GET request, provide the template to show. in most cases, the password reset form.
else:
return render(request, 'account/password_reset_from_key.html')
I added the allowany permission as the API endpoint does not need any authentication.
In URLs;
path('password/reset/<str:uid>/<str:token>/',
reset_user_password,
name='reset_user_password'),
Finally, on the main settings file, I updated the Djoser reset password URL to match the URL I'm building above so that I ensure that the user is redirected to the page I'm intending.
DJOSER = {
"PASSWORD_RESET_CONFIRM_URL":
"dashboard/auth/password/reset/{uid}/{token}/",
}

using django-email-as-username how can I return with a message to the user?

I am trying to use django-email-as-username and I can't find a way to return to the login page with a message for the user in case the data provided by the user is wrong.
this my urls.py
url(r'^login$', 'django.contrib.auth.views.login', {'authentication_form': EmailAuthenticationForm}, name='login'),
this is my views.py
def login_user(request):
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
if email and password:
user = authenticate(email=email, password=password)
if user:
return HttpResponseRedirect('/')
else:
message = 'No such user'
else:
message = 'both email and password are required!'
else:
message = 'wrong method!'
I think you've made an error in that you're providing your own login_user view in your views.py module, but linking to Django's django.contrib.auth.views.login in your URL conf.
You should probably just use django.contrib.auth.views.login as the login view.
You'll also need to provide a registration/login.html template. You'll be able to get at the error information, as the form is passed through to the context. You can use the admin's login template as an example.
In case of authentication failure, you have to render/redirect your own login page with {{ message }}