I'm creating a registration and login app with Django. I get the data using a form and POST.
I want to save the form data into two Django models:
class Customer(models.Model):
username = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
And the Django User model.
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import *
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
Registration View.py
def registerPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
form2 = Customer
print(form)
if form.is_valid():
form.save()
user = form.cleaned_data.get('username')
name = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
form2.save(user, name, email)
messages.success(request, 'Account was created for ' + user)
return redirect('login')
context = {'form': form}
return render(request, 'login/register.html', context)
Now my question is, how do I save the form data into the user models AND save the data(user, name, email) into the Customers model?
I tried using form2.save(user, name, email) but i get an error message:
'str' object has no attribute '_meta'
Thank for any help!
Edit:
I tried the solution of #Moha369, but now I get an error message saying:
Cannot assign "'test1.2'": "Customer.username" must be a "User" instance
Technically its not possible because you are declaring the model previously in meta in the form creation.
But i think the simplest solution might be creating a new object from cleaned data.
user = form.cleaned_data.get('username')
name = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
obj = Customer(username = user, name = name, email = email)
obj.save()
form.save()
EDIT I apologize i missed the part where username is a User object, edited answer:
user = form.cleaned_data.get('username')
name = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
u = form.save()
obj = Customer(username = u, name = name, email = email)
obj.save()
What happened here is that save() method returns the object we've just saved, so we assigned it to u and used it to create the new object.
Related
I customized the User Model Using Django One To One Field
My models.py
class StaffUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.ForeignKey(Dept, on_delete=models.RESTRICT)
def __str__(self):
return self.user.username
When uploading a form, i want to get the department of the user
'My Views.py'
def FileUploadForm(request, pk):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=False)
u = User.objects.get(username=request.user)
form.instance.username = u
folder = Folder.objects.get(id=pk)
department = u.staffUser.department
form.save()
messages.success(request, f'File Successfully uploaded to {folder} in {department}!')
return redirect('home')
else:
form = UploadFileForm()
context = {'pk':pk, 'form':form}
return render(request, "pages/fileup_form.html", context)
But it gives error
AttributeError at /file/new/1
'User' object has no attribute 'staffUser'
Please guys i need help
Add related_name on your user field in StaffUser model
class StaffUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name=staff_user)
department = models.ForeignKey(Dept, on_delete=models.RESTRICT)
def __str__(self):
return self.user.username
Now you will be able to access StaffUser by staff_user on User object
You need to specify the reverse in lower case, so staffuser instead of staffUser.
Alternatively you can specify the related name to be used for calling the reverse accessor, as per below in place of some_name.
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name=some_name)
I created a user profile update page. There are several fields like name, surname, email, profile picture and password. If you leave the password field blank, parts other than the password can be updated. If you If you want to change the password, you can fill in the password field.
When a user updates their fields other than the password, the page redirects the user to the homepage, which is something we want. But when the user wants to change the password, the user gets logout and redirect to the logout page. How can I fix it and redirect the user to the homepage?
views.py
#login_required
def update_user(request, id):
user = get_object_or_404(UserProfile, id=id)
form = SignUpChangeForm(request.POST or None, request.FILES or None, instance=user)
if form.is_valid():
form.save()
if form.cleaned_data['password1'] != "":
user.set_password(form.cleaned_data['password1'])
user.save()
return redirect('home')
context = {
'form': form,
}
return render(request, "update_user.html", context)
forms.py
class SignUpChangeForm(forms.ModelForm):
password1 = forms.CharField(max_length=250, required=False,
label="New Password (leave blank if you do not want to change it)",
widget=forms.PasswordInput)
password2 = forms.CharField(max_length=250, required=False,
label="New Password Confirmation (leave blank if you do not want to change it)",
widget=forms.PasswordInput)
class Meta:
model = UserProfile
fields = ('username', 'first_name', 'last_name', 'email', 'image')
widgets = {
'password1': forms.PasswordInput(),
'password2': forms.PasswordInput(),
}
def clean(self):
cleaned_data = super(SignUpChangeForm, self).clean()
if cleaned_data['password1'] != cleaned_data['password2']:
raise ValidationError("Password confirmation does not match!")
return cleaned_data
models.py
class UserProfile(AbstractUser):
company = models.ForeignKey(CompanyProfile, on_delete=models.CASCADE, null=True, unique=False)
user_id = models.UUIDField(default=uuid.uuid4(), editable=False, unique=True)
username = models.CharField(max_length=500, unique=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
password = models.CharField(max_length=250)
email = models.EmailField(max_length=254)
rank = models.ForeignKey(Rank, on_delete=models.CASCADE, null=True, unique=False)
image = models.ImageField(upload_to='profile_image', blank=True, null= True, default='profile.png')
isUserActive = models.BooleanField(default=False)
You can log the user in again:
from django.contrib.auth import login as auth_login
#login_required
def update_user(request, id):
user = get_object_or_404(UserProfile, id=id)
form = SignUpChangeForm(request.POST or None, request.FILES or None, instance=user)
if form.is_valid():
form.save()
if form.cleaned_data['password1'] != "":
user.set_password(form.cleaned_data['password1'])
user.save()
auth_login(request, user)
return redirect('home')
context = {
'form': form,
}
return render(request, 'update_user.html', context)
It is however not really clear why you pass an id to the view. Right now everyone can edit another user, since I simply have to login and use the id of another user to change their password. Why not work with request.user as the instance?
Note: Usually it is not a good idea to work with SignUpChangeForm(request.POST or None, request.FILES or None).
It is possible that you make a POST request with no data, but still valid, for example if no
fields are required. Normally you check if it is a POST request, and then construct a form with SignUpChangeForm(request.POST, request.FILES).
I Want To Save image in folder using django but i get this error:
MultiValueDictKeyError at /lunchpk/signup/
i need to fix any help will be appreciated
i also see more questions but i don't get correct answer so please answer my question don't add it to duplicate
here's my views.py
def signup(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = NewForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'Profile_Image' in request.FILES:
profile.Profile_Image = request.FILES['profile_pics']
# profile.Dish_Image = request.FILES['Dish_pic']
profile.save()
registered = True
else:
print(user_form.errors,profile_form.errors)
else:
user_form = UserForm()
profile_form = NewForm()
return render(request,'html/signup.html',{'user_form':user_form,'profile_form':profile_form,'registered':registered})
Here is my model.py
class UserInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
Profile_Image = models.ImageField(upload_to='profile_pics',null=True, blank=True)
Dish_Image = models.ImageField(upload_to='Dish_pic',null=True, blank=True)
Dish_Name = models.CharField(max_length=10,)
def __str__(self):
return self.user.username
here is my forms.py
from django import forms
from django.contrib.auth.models import User
from .models import *
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username','email','password')
class NewForm(forms.ModelForm):
class Meta:
model = UserInfo
fields = ('Profile_Image','Dish_Image','Dish_Name')
You're asking for a key 'profile_pics' in request.FILES, but it's not there.
In a regular dict you'd get a KeyError. However, there can be multiple request parameters with the same name, so Django uses a MultiValueDict, which has its own MultiValueDictKeyError.
I think you want request.FILES['Profile_Image'] instead of request.FILES['profile_pics'].
I have made a form having fields of personal information and login information as one
models.py
class EmployeeModel(models.Model)
employee_id = models.CharField(max_length=300,unique=True,help_text='Employee ID should not be same')
name = models.CharField(max_length=300)
username = models.CharField(max_length=50,null=True,blank=True)
email = models.EmailField(null=True,blank=True)
password = models.CharField(max_length=20,null=True,blank=True)
password_confirm = models.CharField(max_length=20,null=True,blank=True)
forms.py
class EmployeeForm(forms.ModelForm):
class Meta:
model = employeeModel
fields = ('__all__')
views.py
User = get_user_model()
def create_view(request):
if request.method == 'POST':
form = employeeForm(request.POST or None,request.FILES or None)
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
User= get_user_model()
user= User.objects.create_user(username=username,email=email,password=password)
authenticate(request,username=username,email=email,password=password)
form.save()
return redirect('emp_list')
else:
form = employeeForm()
return render(request,'create_employee.html',{'form':form})
Its not showing any error but User.objects.all() shows only superuser not the users i created though this form. Those users i have created in this form are are showing up in Employee.objects.get(username='foo')
So what to do? I cant login through those non_superusers. it throws invalid login error. How to fix this?
I have a form used to create new posts in a blog, and one of the fields in that form is the owner, which means who is posting it, but that should be taken from login view when user provides his/her login information I don't want the user selecting who is the owner from a list, it should be automatically populated and fixed with his username. I tried different ways, fixing the value on my forms.py but didn't work, it doesn't recognizes the variable. This is my forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('website', 'picture')
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category','owner')
Here is what I have on models:
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
datposted = models.DateTimeField('date posted')
category = models.ForeignKey('Category')
owner = models.ForeignKey('UserProfile')
def __str__(self):
return '%s' % self.title
This is my view:
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.datposted = datetime.datetime.now()
#post.owner = request.user()
post.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
Could you please help with more details?
I think you just have to remove the 'owner' field from the form and make sure that you handle populating the owner in your view
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category')
view
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
Posts = form.save(commit=False)
# replace below with however you get user profile
Posts.owner = get_user_profile_from_logged_in_user()
Posts.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
This case is covered in django docs:
https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#the-save-method