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)
Related
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.
How I can add data to form that user submitted ? I want the user to fill in the "name" and "done" in the form and automatically add "user" (creator) and "board"
code:
#views.py
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = Board.objects.filter(user=request.user).get(pk=pk)
form = AddTaskForm()
if request.method == "POST":
form = AddTaskForm(request.POST)
if form.is_valid():
form.initial['user'] = request.user
form.initial['board'] = board
# that doesn't seem to work....
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
#forms.py
class AddTaskForm(ModelForm):
class Meta:
model = Task
fields = "__all__"
exclude = ('user', 'board',)
#models.py
class Board(models.Model):
title = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
title = models.CharField(max_length=200, null=True)
done = models.BooleanField(default=False, null=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
board = models.ForeignKey(Board, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
You can edit the instance wrapped in the form:
from django.shortcuts import get_object_or_404
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = get_object_or_404(Board, user=request.user, pk=pk)
form = AddTaskForm()
if request.method == 'POST':
form = AddTaskForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.instance.board_id = pk
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
I created my model that have authUser referenced as foreign key, then using django Form API i am trying to store data into my DB but my user field remains null.
I have used build-in FORM API to receive an uploaded file and before storing my file, i also store filename. I tried to do the same for userField but django throw ValueError.
Models.py
class sample(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True ,default=1)
submit_time = models.DateTimeField(auto_now=True)
file_name = models.CharField(max_length=1024)
score = models.FloatField(default=0.0)
is_pending = models.BooleanField(default=True)
is_complete = models.BooleanField(default=False)
json_URL = models.FilePathField()
sample = models.FileField(upload_to='samples/')
Views.py
#login_required
def upload(request):
if request.method == 'POST':
file = request.FILES['sample']
form = SampleForm(request.POST, request.FILES)
if form.is_valid():
new_sample = form.save(commit=False)
new_sample.file_name = file.name
new_sample.user = User.id #throws ValueError Cannot assign "sample.user" must be a "User" instance.
form.save()
return redirect('reports')
else:
print("form is invalid")
else:
form = SampleForm()
if request.method == 'GET':
return render(request, 'upload2.html', {'form': form})
forms.py
class SampleForm(forms.ModelForm):
class Meta:
model =sample
fields=('sample',)
my goal is to save the user id in my db so i know who uploaded the file.
You should use request.user to the new_sample.user object, or request.user.id (or request.user.pk) to the request.user_id attribute, like:
# …
new_sample = form.save(commit=False)
new_sample.file_name = file.name
new_sample.user = request.user
form.save()
return redirect('reports')
# …
By using User.id, you get a reference to the field of the User model, not an object.
I created a model for registered users and added a field feedback in it. I need to allow logged in users to post feedback and to get it updated in the model, but it is not. Instead it is getting created as a new entry with a primary key.
model for register
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE, default=None, null=True)
role = models.CharField(max_length=50, choices=Roles, default='client')
feedback = models.TextField(max_length=500,blank=True)
verified =models.BooleanField(default = False,blank=True)
def __str__(self):
return self.user.username
form for feedback:
class FeedbackForm(forms.ModelForm):
class Meta():
model = UserProfile
fields = ('feedback',)
view for feedback:
#login_required
def feedback(request):
if request.method == "POST":
form = FeedbackForm(request.POST)
else:
form = FeedbackForm()
if form.is_valid():
userprofile=form.save(request)
userprofile.save()
else:
form = FeedbackForm()
return render(request, 'NewApp/feedback.html',{'form':form})
You need to pass in the current profile as the instance parameter.
form = FeedbackForm(request.POST, instance=request.user.userprofile)
I am trying to create a form that allows users to edit their profile data. As such I want to have the most recent data from the database be displayed when the user goes to edit the form. Heres what I have so far:
# models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
location = models.CharField(max_length=30, blank=True)
birthdate = models.DateField(null=True, blank=True)
def __str__(self):
return self.user.username
# forms.py
class EditProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['location', 'birthdate']
# views.py
class EditProfileFormView(View):
form_class = EditProfileForm
template_name = 'forums/edit-profile.html'
def get(self, request, username):
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise Http404('The User "' + username + '" could not be found.')
if (not request.user.is_authenticated):
return HttpResponseForbidden()
elif (user.id is not request.user.id):
return HttpResponseForbidden()
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
Setting the form to form_class(None) is what gives me an empty form, however dropping user.profile in the same spot gives me an error 'Profile' object has no attribute 'get'
Try populating the form with an instance
form = self.form_class(instance=user.profile)
Note: this would probably be easier with a standard UpdateView