I have a page for updating a user profile in my django project. The view code looks like this:
#login_required
def updateProfile(request, user_id):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
form.user_id = user_id
form.save(commit=True)
return index(request)
else:
profile, created = UserProfile.objects.get_or_create(user_id = self.user_id) # don't know if this will actually work.
profile_form = UserProfileForm(profile)
context = {
'user' : request.user,
'form' : profile_form
}
return render(request, 'myapp/profile.html', context)
My form looks like this:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['age', 'skill_level']
My user profile looks like this:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
age = models.IntegerField(default=18)
skill_level = models.ForeignKey(SkillLevel)
When this gets posted to, we receive what appears to be a valid user_id along with a valid form. In the UserProfileForm form we do not include user_id so that when it renders the user cannot decide to swap that out. Instead, the user_id gets posted back as a separate parameter (as I type this out, I realize it's kind of weird..). I want to save the UserProfile encapsulated by UserProfileForm to the database on post, so I give it a user_id and try to call .save(commit=True) on it, which returns "Column 'user_id' cannot be null".
My question is simple, how can I get that underlying UserProfile object saved from the form data with the information at hand?
Standard Django form handling idiom in case like that is
#login_required
def updateProfile(request, user_id):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
obj = form.save(commit=False) # Get just object, but don't save yet
obj.user = request.user # set user (or user_id)
obj.save() # Save object
return index(request)
else:
profile, created = UserProfile.objects.get_or_create(user_id = self.user_id) # don't know if this will actually work.
profile_form = UserProfileForm(profile)
context = {
'user' : request.user,
'form' : profile_form
}
return render(request, 'myapp/profile.html', context)
Note that form data is not in fields, so form.my_field = 123 won't work - form data is parsed to form.cleaned_data dictionary where form.save() reads it.
use the request.user for userProfile user, do this way
#login_required
def updateProfile(request, user_id):
if request.method == 'POST':
form = UserProfileForm(request.POST)
form.user = request.user
if form.is_valid():
form.save(commit=True)
return index(request)
else:
profile, created = UserProfile.objects.get_or_create(user = request.user) # don't know if this will actually work.
profile_form = UserProfileForm(instance=profile)
context = {
'user' : request.user,
'form' : profile_form
}
return render(request, 'myapp/profile.html', context)
Related
Whenever I try to create a "Tour" for a "User" I get this error:
"DoesNotExist at /add-tour/FAjK5CryF8/ - User matching query does not exist."
Specifically the problems seems to come from this line of code:
user = User.objects.get(pk=pk)
models.py
class Tour(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
tour_date = models.DateField(default=date.today)
tour_fans = models.ForeignKey(FanAccount, on_delete=models.PROTECT)
def __str__(self):
return f"{self.user} del {self.tour_date}"
views.py
def tour_new(request, pk):
user = User.objects.get(pk=pk)
if request.method == "POST":
form = TourForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.tour_fans = request.user
form.instance.user = user
instance.save()
form.save()
return render(request, "tour.html", {"form": TourForm(), "success": True})
else:
form = TourForm()
return render(request, "tour.html", {"form": form})
For "User" I'm using a custom Primary Key (ShortUUID).
I'm new to Python and Django so it may be something easily solvable, but after hours of attempts I seem unable to solve it.
You need to make sure your user instance does exist, so you should instead of user = User.objects.get(pk=pk)call user = get_object_or_404(User, pk=pk), then you need to pass user as an instance:
if request.method == "POST":
form = TourForm(request.POST, instance=user)
I'm pretty new to Django, I've been stuck on this view for a little while. My goal with this form is to be able to create a small note on a "Property" about maintenance or other information. The note would log the time, date, note and the user that recorded the note. Any help would be appreciated.
View:
#login_required(login_url="login")
def createNote(request, pk):
PropertyNoteFormSet = inlineformset_factory(
Property, PropertyNote, fields=('note', 'user',))
property_note = Property.objects.get(id=pk)
form = PropertyNoteFormSet(instance=property_note)
# form = OrderForm(initial={'customer': customer})
if request.method == "POST":
print(request.POST)
form = PropertyNoteFormSet(
request.POST, instance=property_note)
if form.is_valid():
form.save()
return redirect("/")
context = {"form": form}
return render(request, "dashboard/create_note.html", context)
Here is the ModelForm:
class PropertyNoteForm(ModelForm):
class Meta:
model = PropertyNote
fields = ['note']
exclude = ['user']
Here is the Model:
class PropertyNote(models.Model):
airbnb_name = models.ForeignKey(Property, blank=True,
null=True,on_delete=models.CASCADE)
note = models.TextField(blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.note
The form comes out with around 4 boxes to fill in. Currently it works, but you have to actually select the user that is posting the note, I would like this part to be handled automatically and use the current logged in user. I think I still have a whole lot of holes in my knowledge around this stuff, I just can't seem to work it out.
Thanks in advance.
Edit:
I've tried this:
def createNote(request, pk):
PropertyNoteFormSet = inlineformset_factory(
Property, PropertyNote, fields=('note',), extra=1)
property_note = Property.objects.get(id=pk)
form = PropertyNoteFormSet(
queryset=PropertyNote.objects.none(), instance=property_note)
# form = OrderForm(initial={'customer': customer})
if request.method == "POST":
print(request.POST)
form = PropertyNoteFormSet(
request.POST, instance=property_note)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
print(instance.user)
instance.save()
return redirect("/")
context = {
"form": form,
'pk': pk,
}
return render(request, "dashboard/create_note.html", context)
But I get this:
AttributeError at /create_note/75/
'list' object has no attribute 'user'
Request Method: POST
Request URL: http://127.0.0.1:8000/create_note/75/
Django Version: 3.0.4
Exception Type: AttributeError
Exception Value:
'list' object has no attribute 'user'
you can use request.user.id to get the logged user id in your view.
See Documentation in Django
#login_required(login_url="login")
def createNote(request, pk, **kwargs):
note_form = PropertyNoteForm()
if request.method == "POST":
note_form = PropertyNoteForm(request.POST)
if note_form.is_valid():
add_note = note_form.save(commit=False)
add_note.user = request.user
add_note.airbnb_name =
Property.objects.get(id=pk)
add_note.save()
return redirect('/property/' + pk + '/')
context = {
"form": note_form,
'pk': pk,
}
return render(request, "dashboard/create_note.html", context)
I solved it with the above code. Using instance was the incorrect thing to do here. I didn't need to create an instance and I didn't need the inline form. I simply needed a new form:
note_form = PropertyNoteForm()
The user input information, I need to send that information to check if it's valid:
if request.method == "POST":
note_form = PropertyNoteForm(request.POST)
if note_form.is_valid():
Then I needed to populate the form with information that was not already in the form from the user:
add_note = note_form.save(commit=False)
add_note.user = request.user
add_note.airbnb_name = Property.objects.get(id=pk)
add_note.save()
return redirect('/property/' + pk + '/')
I have two forms, one CreateOrderForm and one CreateManifestForm. Submitting CreateOrderForm renders CreateManifestForm.
There is an input in CreateOrderForm 'reference' which is user entered but then should default into the 'reference field of CreateManifestForm. I seem to be unable to figure out how to pass that value from form to form
FORMS.PY
class CreateOrderForm(forms.ModelForm):
class Meta:
model = Orders
fields = ('reference', 'ultimate_consignee', 'ship_to', 'vessel', 'booking_no', 'POL',....)
class CreateManifestForm(forms.ModelForm):
class Meta:
model = Manifests
fields = ('reference', 'cases', 'description', 'count')
VIEWS.PY
def add_order(request):
if request.method == "POST":
form = CreateOrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('add_manifest')
else:
form = CreateOrderForm()
return render(request, 'add_order.html', {'form': form})
def add_manifest(request):
if request.method == "POST":
form = CreateManifestForm(request.POST)
if form.is_valid():
form.save()
return redirect('add_manifest')
form = CreateManifestForm()
manifests = Manifests.objects.all()
context = {
'form': form,
'manifests': manifests,
}
return render(request, 'add_manifest.html', context)
As you can see there is a field in each form for 'reference' I would like to user enter it in CreateOrderForm and pass that value to default when creating the manifest. Any help is greatly appreciated and thank you in advance.
There is a solution that you can try:
make the add_manifest URL have a Parameter like
path('add-manifest/<int:reference_id>/', name='add_manifest`)
and in your View update:
return redirect('add_manifest') # in add_order function
to:
return redirect('add_manifest', kwargs={'reference_id': form.reference})
now in the add_manifest View you can access the Reference from:
request.resolver_match.kwargs.get('reference_id')
I have a Django form that allows a user to save their UserProfile details, but it only allows this to occur once. Given that additional saves ask to create a new entry, but i have a one-to-one relation between the user field and user UserProfile field.
When a user is created a UserProfile entry is not created. Rather they cannot access their account until these details are filled out.
I want to pre-populate the form with existing data when a student goes to access the form a second time.
def student_details(request):
#this is a form
if request.user.is_authenticated():
if request.method == 'POST':
form = DetailsForm(request.user, request.POST, request.FILES)
if form.is_valid():
note = form.save(commit=False)
note.user = request.user
note.completed_form = True
note.save()
return HttpResponseRedirect('/student-portal/')
else:
if request.user.get_profile():
pass
form = DetailsForm(request.user)
else:
form = DetailsForm(request.user)
return render_to_response("student-details.html", {'form': form}, context_instance=RequestContext(request))
return HttpResponseRedirect('/')
Sorry guys just found out how to do this:
def student_details(request):
#this is a form
if request.user.is_authenticated():
if request.method == 'POST':
form = DetailsForm(request.user, request.POST, request.FILES)
if form.is_valid():
note = form.save(commit=False)
user_profile = UserProfile.objects.get(user=request.user)
if user_profile:
note.id = user_profile.id
note.user = request.user
note.completed_form = True
note.save()
return HttpResponseRedirect('/student-portal/')
else:
try:
user_profile = UserProfile.objects.get(user=request.user)
form = DetailsForm(request.user, instance=user_profile)
except:
form = DetailsForm(request.user)
return render_to_response("student-details.html", {'form': form}, context_instance=RequestContext(request))
return HttpResponseRedirect('/')
The idea here is to query to see if a user_profile linked to that user already exists and then specify the ID for that entry.
Let's say I have a form for adding/editing products (with field 'user' being a foreign key to my User) triggered from two separate view functions - add/edit :
def product_add(request):
userprofile = UserProfile.objects.get(user=request.user)
if request.method == 'POST':
form = ProductAddForm(request.POST, request.FILES,)
if form.is_valid():
form.save(user=request.user)
else:
form = ProductAddForm()
return render_to_response('products/product_add.html', {
'form':form, 'user':request.user,
}, context_instance=RequestContext(request))
def product_edit(request, id):
product = get_object_or_404(Product, id=id, user=request.user)
if product.user.id!=request.user.id:
raise Http404
if request.method == 'POST':
form = ProductAddForm(request.POST, request.FILES, instance=product)
if form.is_valid():
form.save(user=request.user)
else:
form = ProductAddForm(instance=product)
return render_to_response('products/product_edit.html', {
'form':form, 'user':request.user,
}, context_instance=RequestContext(request))
The form's save method looks as follows :
def save(self, user, *args, **kwargs):
self.instance.user = user
post = super(ProductAddForm, self).save(*args, **kwargs)
post.save()
Can somebody tell me what's happening in this save method step by step ?Why do we call super on this form and what is the difference in whole processing when we edit and save new product if function call is the same ?
self.instance.user = user
Save the user argument into the self.instance object's user attribute
post = super(ProductAddForm, self).save(*args, **kwargs)
Invoke the superclass save method to get a resulting object.
post.save()
Save the resulting object. This may be needless, or it may be essential, depending on the arguments to save.
See http://docs.djangoproject.com/en/1.2/topics/forms/modelforms/#the-save-method. If commit is False, then the post object has not been saved to the database.