I want to edit my user data from template, bellow are my codes.
def guru_edit(request, id):
Guru = get_object_or_404(DataGuru, GuruUser_FK_id=id)
GuruUser = get_object_or_404(User, id=id)
if request.method == 'POST':
form_guru = dataguruform(request.POST, instance=Guru)
form_user = userform(request.POST, instance=GuruUser)
if form_guru.is_valid() and form_user.is_valid():
form_guru.save()
form_user.save()
return redirect('index_guru')
else:
form_guru = dataguruform(instance=Guru)
form_user = userform(instance=GuruUser)
return render(request, 'guru/guru_tambah.html', {'form_user': form_user,'form_guru':form_guru})
this is my forms.py
class userform(ModelForm):
class Meta:
model = User
fields = ('username','email', 'password','is_staff','is_active','is_superuser')
widgets={
'password':TextInput(attrs={'type':'password'})
}
But when i was save from template, the password is not encrypted like it used to be, but just plaintext.
How to make it encripted?
Do not set the password via a form field. Set the password with User.set_password() method which accepts your unencrypted password:
user_form = UserForm(request.POST, instance=user)
if user_form.is_valid():
user = user_form.save()
user.set_password('unencrypted_password') # replace with your real password
user.save()
return redirect('index_guru')
I have named the variables and forms in a bit more Django-ish way here, as you can see.
Background: The password in Django is stored as a (most commonly PBKDF2) hash in your database. set_password takes care of seeking the correct hashing method and salting and hashing your passwords correctly.
Forms should merely contain something like password and password_check fields that are used to check if your user inputs his or her password correctly. They should not be used to save a plain password into your database, which I suspect is happening here by default.
You can use set_password inside your forms as well by overriding the UserForm.save() method.
Take the time to read through this document:
https://docs.djangoproject.com/en/dev/topics/auth/passwords/
Just create a view using Django's built in forms and views:
In your views.py:
from django.contrib.auth.views import PasswordChangeView
from django.contrib.auth.forms import PasswordChangeForm
class UpdatePassword(PasswordChangeView):
form_class = PasswordChangeForm
success_url = '/user/edit-profile'
template_name = 'app/change-password.html'
Inside your urls.py:
from . import views
urlpatterns = [
path('/change-password', views.UpdatePassword.as_view(), name="update_password"),
]
Related
How to add username of currently logged in user to field in my model? For example, I need to store info about user like name, email and so on in model, other than default Django user model, but I still use default one to store credentials. I want to establish relationship between those, so I created username field in my model. How do I fill it with current user's username upon saving the corresponding form?
My model
class ApplicantProfile(models.Model):
name = models.CharField(max_length = 50)
dob = models.DateField()
email = models.EmailField()
description = models.TextField()
username = <something>
What do I change <something> with?
My form
class ApplicantProfileEdit(forms.ModelForm):
class Meta:
model = ApplicantProfile
fields = [
'name',
'dob',
'email',
'description',
]
My view
def ApplEditView(request):
form = ApplicantProfileEdit(request.POST or None)
if form.is_valid():
form.save()
form = ApplicantProfileEdit()
context = {
'form':form
}
return render(request, "applProfileEdit.html", context)
P.S. I tried to import models straight to my views.py, and assign request.user.username to username field of the model in my view, but it didn't work, just left that field empty. I had username as CharField when I tried this.
It is not a good idea to save the username itself, or at least not without a FOREIGN KEY constraint. If later a user changes their name, then the username now points to a non-existing user, if later another user for example changes their username to thatusername, then your ApplicantProfile will point to the wrong user.
Normally one uses a ForeignKey field [Django-doc], or in case each ApplicantProfile points to a different user, a OneToOneField [Django-doc]:
from django.conf import settings
from django.db import models
class ApplicantProfile(models.Model):
name = models.CharField(max_length = 50)
dob = models.DateField()
email = models.EmailField()
description = models.TextField()
# maybe a OneToOneField
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
In the view:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def appl_edit_view(request):
if request.method == 'POST':
form = ApplicantProfileEdit(request.POST)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('some-view-name')
else:
form = ApplicantProfileEdit()
context = {
'form':form
}
return render(request, 'applProfileEdit.html', context)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Im trying to create a form that would allow me to add a profile picture to the custom User object. I know that there is OneToOne method, although I want it to be stored directly in User.
You need to extend default User Model like this:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
"""Add more fields to default user model."""
profile_pic = models.ImageField(upload_to='profile_pics', blank=True, null=True)
Now you need to edit your settings.py to make your custom User model the default auth model. Add this line in your settings.py:
AUTH_USER_MODEL = 'myApp.User'
myApp is the name of app in whose models.py your created your Custom User Model.
And that's all, now the default auth model is your custom model User which is exactly the same as the Django default auth model except it has an additional field profile_pic to store an image.
Form to add picture should be like this:
class profilepictureForm(forms.ModelForm):
"""Form to add profile picture to User model."""
class Meta:
"""Meta class for profilepictureForm."""
model = User
fields = ('profile_pic', )
And in your views you should use this form like this:
def add_profile_picture(request):
if request.method == 'POST':
form = profilepictureForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
form.save()
return HttpResponseRedirect('/success/url/')
else:
form = profilepictureForm(instance=request.user)
return render(request, 'userpanel/profilepicture.html', {'form': form})
Have a look on below code
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})
For more information please check https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
I'm trying to add data from UserCreationForm extra fields to database, i want to add multiple fields to UserCreationForm and save it to database. I saw other examples from topics here in stackoverflow, but it doesn't work.
Here is a example of my code:
( fields: "agree_terms" or "price" could be anything else)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(widget = forms.EmailInput(attrs=
{'placeholder':'Email'}))
agree_terms = forms.BooleanField()
price = forms.DecimalField(decimal_places=2, max_digits=10000)
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('username', 'password1',
'email','password2','agree_terms','price')
views.py
#csrf_protect
def registers(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
print(form)
print(form.is_valid())
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request,'Conta criada {}'.format(username))
return redirect('login')
else:
form = UserRegisterForm()
return render(request,'header-login.html',{'form':form})
Did you also changed your User model to support those fields? You'd need to add them to the model/table as well.
Although, I wouldn't recommend piling up so much extra data directly on the User model.
So I've been trying my hand at Django authentication. I tried to create a register view which implements two models the django.contrib.auth.models.User and one custom model which shares a OneToOne relationship with User.
Here's the relevant code
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(User)
SapID = models.IntegerField(default=60000000000)
def __str__(self):
return self.user.username
views.py
from django.shortcuts import render
from .forms import UserFormRegister, UserForm
# Create your views here.
def register(request):
if request.method == 'POST':
user_form = UserForm(data = request.POST)
users_form = UserFormRegister(data = request.POST)
if user_form.is_valid() and users_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
userregister = users_form.save()
userregister.user = user
userregister.save()
return redirect('/#/')
else:
user_form = UserForm()
users_form = UserFormRegister()
return render(request, 'register.html',{'user_form':user_form, 'users_form':users_form},)
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import UserProfile
class UserForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta:
model = User
fields=('username','password','email','first_name','last_name',)
class UserFormRegister(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('SapID', )
SapID is a unique id that each user will have.
Now,when I try to register, the user object gets created but the user profile object doesnt. I get an error saying "NOT NULL constraint failed: foo_userprofile.user_id". What am I missing?
The issue, is when you do users_form.save(), it actually tries to create at object, and save it to the database where the constraint raises exception. To avoid this, you can use the commit=False argument which creates the profile object in memory, but does not save it to the database just yet.
userregister = users_form.save(commit=False)
userregister.user = user
userregister.save()
More on commit=False:
This save() method accepts an optional commit keyword argument, which
accepts either True or False. If you call save() with commit=False,
then it will return an object that hasn’t yet been saved to the
database. In this case, it’s up to you to call save() on the resulting
model instance. This is useful if you want to do custom processing on
the object before saving it, or if you want to use one of the
specialized model saving options. commit is True by default.
today I'm trying to get and print all my users emails, who had chose selection "Value1".
This is how my model.py looks like:
from django.db import models
class Vartotojas(models.Model):
email = models.EmailField()
option = models.CharField(max_length=30)
Forms.py :
from django import forms
from emailai.models import Vartotojas
class VartotojasForm(forms.Form):
email = forms.EmailField(max_length=100)
my_field = forms.MultipleChoiceField(choices=(('Value1','Value1'),('Value2','Value2')), widget=forms.CheckboxSelectMultiple())
def save(self):
mymodel = Vartotojas(
email=self.cleaned_data['email'],
option=self.cleaned_data['my_field'],
)
mymodel.save()
And finally my views.py "
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from emailai.models import Vartotojas
from renginiai.forms import VartotojasForm
def name(request):
if request.method == 'POST':
form = VartotojasForm(request.POST)
if form.is_valid():
a = Vartotojas.objects.filter(option="u'Value1'") # How to do it right?
# Now How To Get those object emails?
new_user = form.save()
return render(request, "Vartotojas-result.html", {
'form': form, #BLABLABLA,
})
else:
form = VartotojasForm()
return render(request, "Vartotojas-form.html", {
'form': form,
})
I commented my questions inside my views.py. I hope you will be able to help me. Thank you in advance!
I re-write my code with getlist. Now it looks like this:
views.py :
if form.is_valid():
email = form.cleaned_data['email']
option = request.POST.getlist('my_field')
new_user = form.save(email, option)
forms.py:
email = forms.EmailField(max_length=100)
my_field = forms.MultipleChoiceField(choices=(('Value1','Value1'),('Value2','Value2')), widget=forms.CheckboxSelectMultiple())
def save(self, email, option):
mymodel = Vartotojas(
email=email,
option = option,
)
mymodel.save()
As you see I pasted just most important places. By the way, users can choose 2 values, that's why I use checkbox. But still it not working.
I believe you want to use the values_list property like so:
Vartotojas.objects.filter(option=u"Value1").values_list("email", flat=True)
to get a list of all email addresses. You may also want to apply a distinct() to that if you're not already preventing duplicates. On a side note, look into ModelForms: it looks like that would save you a fair bit of the time/ code you have written for dealing with this. You could create a ModelForm based on your Vartotojas object and not have to write the explicit save() method you have.