Problems when obtaining an id, sent by a form - django

Good evening, I am trying to get the id of my model Note that is sent by means of a form, but when I put form.id it tells me that id is not defined, try to get it through the user session but it says that it was not found.
def add_book(request):
template_name = 'books/create_note.html'
book = get_or_create_book(request)
form = NoteForm(request.POST)
if request.method == 'POST' and form.is_valid():
note = Note.objects.get(pk=form.pk)
book.notes.add(note)
form.save()
return redirect('books:book')
return render(request, template_name, {
'form': form,
})
and this is the form
class NoteForm(ModelForm):
class Meta:
model = Note
fields = (
'title', 'nota'
)
labels = {
'title': 'Titulo',
'nota': 'Nota',
}
try creating an instance of my Note model but when it comes time to create it tells me it is empty.

I'm new to Django, but I had similar problems that frustrate me. not sure if I have the hang of it yet, but I think what might be happening is that when you first go to the page there is a GET request, so your if statement misses it. It then it reaches the last line and goes to template_name without the form being assigned so the form never gets a Post requests. In the terminal you can see the POST and GET requests. I ended up also printing out request.method a lot before and after if statements just to help trace what was going on.
else:
form=NoteForm()
Then your return render(request,....
making sure it goes back to the correct html page.
The thing that worked for me eventually was something like
def Search_Page(request):
if request.method=='POST':
form = Search_Page_Form(request.POST)
if form.is_valid():
do some stuff and save the change to the model
return(redirect('mainapp:Evaluate_Page'))
else:
form=Search_Page_Form()
return render(request, 'mainapp/Search_Page.html', {'form': form})

Related

Passing additional information to View

I am trying to handle Django form in a more gentle way and actually, I have no idea how to push further this topic. I have a View which is responsible for displaying a Form, in If form.is_valid() condition I am looking for free parking spots, if I found nothing then I would like to show an Error to the user or pass to context additional data. Fist part I've covered easily but I have no idea how to show an error or something similar.
class BookParkingSpot(FormMixin, generic.ListView):
template_name = 'parking/book_spot.html'
form_class = BookParkingSpotForm
model = ParkingBooking
def post(self, request, *args, **kwargs):
form = BookParkingSpotForm(self.request.POST)
if form.is_valid():
parking_spot_list = ParkingSpot.objects.all().exclude(
parkingbooking__booking_time_start__lte=form.instance.booking_time_end,
parkingbooking__booking_time_end__gte=form.instance.booking_time_start
)
if parking_spot_list.exists():
random_spot = random.choice(parking_spot_list)
reservation = ParkingBooking.objects.create(
car=form.instance.car,
booking_owner=self.request.user,
spot=random_spot,
booking_time_end=form.instance.booking_time_start,
booking_time_start=form.instance.booking_time_end,
)
return redirect(reservation.get_absolute_url())
else: # this part doesn't work
context = self.get_context_data(**kwargs)
return render(self.request, self.template_name, context)
Any idea how to improve it?
Best write your validations in the form methods. Read about in: https://docs.djangoproject.com/en/4.0/ref/forms/validation/#validating-fields-with-clean
from django.core.exceptions import ValidationError
class BookParkingSpotForm(forms.Form):
# ...
def clean(self):
cleaned_data = super().clean()
p_list = ParkingSpot.objects.all().exclude(
parkingbooking__booking_time_start__lte=cleaned_data.booking_time_end,
parkingbooking__booking_time_end__gte=cleaned_data.booking_time_start
)
if p_list.count() == 0:
raise ValidationError('Your error message')
And to access to the form data use form.cleaned_data['field_name'] and not form.instance.field_name.
Sorry everyone for the inconvenient but again after posting on StackOverflow I figured out how to resolve this issue and it was very simple, I am still learning Django ;)
So the answer to my question lies in the last part of my code, if I didn't find any free parking spots then I can render the same page with additional data like on below example and pass form object to context:
return render(self.request, 'parking/book_spot.html',
{'errors': "There are no free parking spots in selected time",
'form': form})

Why won't my text posts save, it worked before?

My text posts were working before adding a notification feature but now they aren't, I have a debug print but instead of seeing the post object, I'm seeing the user that posted it. I haven't changed anything other than getting the post id, timesince and the notify function, I've used the exact same method with my picture and video posts and they work fine, so it doesn't make sense to me. I've got a debug print in the notification function to make sure the post type and id have been passed correctly and those indeed show the id and type
views.py
#login_required()
def text_post(request):
if request.method == "POST":
form = TextPostForm(request.POST)
if form.is_valid():
t_post = form.save(commit=False)
t_post.author = request.user
t_post.save()
id = t_post.id
time = timesince
print(t_post) # t_post shows the user instead of the post
followers = list(request.user.followers.all())
notify(followers,
request.user,
f"{request.user.username} posted {time}",
id,
'text'
)
print(t_post)
#redirect to last page
return redirect('home')
else:
form = TextPostForm()
post_type = 'text'
return render(request, 'create_post.html', {'form': form, 'post_type': post_type})
forms.py
class TextPostForm(forms.ModelForm):
class Meta:
model = TextPost
fields = ('description','privacy', 'categories')

Can't figure out why form.has_changed() is always true?

I'm trying to learn Django and have come up with a situation I can't figure out. I have the following code:
def contact_add(request):
if request.method == 'POST':
form = ContactManageForm(request.POST)
if form.is_valid():
if form.has_changed(): # <-- ALWAYS RETURNS TRUE!
form.clean()
...
elif 'id' in request.GET: # Request to show an existing contact
new_contact_dynamic = contacts.models.PersonDynamic.objects.get(person_static = request.GET['id'],
current_record_fg = True)
form = ContactManageForm(new_contact_dynamic.__dict__, initial=new_contact_dynamic.__dict__)
else: # This must be to add a new contact
form = ContactAddForm()
return render(request, 'contact_manage.html', {'form': form})
So, if I'm sent an ID number, I read a record and display it on the screen. My template gives the user a 'submit changes' button. My problem, as noted above, is that Django always shows that the form has changed, even if the user hasn't changed any data on the screen (i.e. he just hit the submit changes button without changing anything).
So, am I doing something obviously wrong in my code that's creating this situation? Am I misinterpreting how the form.has_changed() method works?
It's my assumption that when I use the initial=parameter after a GET request, Django is storing that data somewhere and knows the context when the user then hits the 'submit data' button, is this wrong?
Yes you need to initialize your Form with initial data.
In your view the GET and POST requests have no common context. You may want to use sessions for that.
But in this case, it is not necessary. You can retrieve the instance on each request:
def contact_add(request):
if 'id' in request.GET:
new_contact_dynamic = contacts.models.PersonDynamic.objects.get(
person_static = request.GET['id'],
current_record_fg = True
)
if request.method == 'POST':
form = ContactManageForm(request.POST, initial=new_contact_dynamic.__dict__)
...
else: # Show an existing contact
form = ContactManageForm(initial=new_contact_dynamic.__dict__)
else:
form = ContactAddForm()
return render(request, 'contact_manage.html', {'form': form})

Update object with model form inside the view

I need to update the object with its model form and passed the instance as described in the django doc. However I am having these problems when saving the form:
When I change the title and submit the form, it gives me an error that the image field is required and image field gets blank. However when the image is changed, the title field is not blank and it does not give any error.
If everything works and submits the form, it creates a new snap object instead of updating the instance object.
In the views I tried using both the obj.save() and obj.update(), but nothing helped. Please help me how to solve this problem. I will really appreciate your help Thank you.
form:
class SnapForm(forms.ModelForm):
class Meta:
model = Snap
fields = ['title', 'description', 'image', 'upload_date']
view:
def admin_snap_settings(request, snap_id):
if not request.user.is_admin:
return render(request, 'admin_login_invalid.html')
else:
instance = Snap.objects.get(id=snap_id)
if request.user == instance.user:
if request.method == "POST":
form = SnapForm(request.POST, request.FILES, instance=instance)
if form.is_valid():
form.save()
return HttpResponseRedirect('/custom123user/admin/snapview')
else:
form = SnapForm(instance=instance)
return render(request, 'admin_snap_settings.html', {
'form': form
})
else:
return render(request, 'wrong_user.html')
After hours of debugging and scratching head... I realized that the url of the action for the form was pointing to admin_snap_add() view and not to the admin_snap_settings() view.
Hope this will help someone so dumb as me. If you guys want me to delete this question please inform me. Thank you for your time.

How to edit/add objects using the same django form?

Hey, I've searched around to do this (particularly this Q: Django edit form based on add form?) but I just can't get it to work.
The problem I'm having is that the form always creates a new object, instead of modifying the existing one.
This is my code:
def new_task(request, task_id=None):
if task_id is not None:
task = Task.objects.get(pk=task_id)
else:
task = Task()
if request.method == 'POST': # If the form has been submitted...
form = TaskForm(request.POST, instance=task)
if form.is_valid():
form.save();
return tasks(request, 'Task #%s created successfully.' % (task.id))
else:
form = TaskForm(instance=task)
return custom_render('user/new_task.html',
{'form': form},
request);
Any clues on what I'm missing? Thanks
Edit: added form definitions.
class TaskForm(ModelForm):
description = CharField(max_length = 1500,
widget= forms.Textarea(attrs={'class':'task-description'}),
required=True)
class Meta:
model = Task
Ok, after a nice night of debugging i found out what the problem was. Quite stupid actually.
The problem was that on submit, task_id was None.
I worked it out by doing:
On the form I added: <form action="{% url App.myapp.views.new_task **task_id** %}"
On my views I added:
return custom_render('user/new_task.html',
{'form': form, 'submit': submit, 'task_id':task.id},
request)
That was it. A newbie mistake. If someone out there knows a nicer way I'm open to suggestions.