How to get selected radio button choice in django form? - django

I've a form
class ScoreUpdateForm(forms.Form):
answer_id = forms.IntegerField()
given_score = forms.FloatField()
CHOICES = [('calculated_score', 'Calculated Score'),
('given_score', 'Given Score')]
final_score = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect())
Here is my template
<form action="/teachers/questions/{{ answer.question.id }}/score" method="post">
{{ form.given_score }}
{{ form.final_score }}
<input type="submit" value="Submit"/>
</form>
here is my view
def score(request, pk):
if request.method == 'POST':
form = ScoreUpdateForm(request.POST)
if form.is_valid():
given_score = form.cleaned_data['given_score']
final_score = form.cleaned_data['final_score']
I can get given_score value but not the final_score. I want to get the value of the selected choice in my view after the post.

try to use
final_score = form.cleaned_data['final_score']
final_score = dict(form.fields['final_score'].choices)[final_score]

Related

Creating new Objects instead of updating - Django

I am trying to use Update in Django, but it is not being updated, rather a new object of the model is being created in the database.
For example, if I try to change product label "Laptop" to "Smartphone", Django creates a new product called "Smartphone" instead of updating "Laptop".
This is my code
Model:
class Products(models.Model):
label = models.CharField(max_length=50)
description = models.CharField(max_length=250)
first_price = models.FloatField(null=True)
price = models.FloatField()
quantity = models.IntegerField(default=0)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.label
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
Form:
class ProductForm(ModelForm):
class Meta:
model = Products
fields = ['label', 'description', 'first_price', 'price', 'quantity', 'image']
View:
#login_required(login_url='login')
def editProduct(request, id):
product = Products.objects.get(id=id)
form = ProductForm(instance=product)
if request.method == 'POST':
form = ProductForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, 'Product was edited.')
return redirect('index')
context = {
'form': form
}
return render(request, 'store/edit-product.html', context)
Template:
<h3>Edit Product</h3>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.label.label }}
{{ form.label }}
{{ form.description.label }}
{{ form.description }}
{{ form.first_price.label }}
{{ form.first_price }}
{{ form.price.label }}
{{ form.price }}
{{ form.quantity.label }}
{{ form.quantity }}
{{ form.image.label }}
{{ form.image }}
<input type="submit" name="Add product">
{{form.errors}}
</form>
Thank you in advance.
To update an object, it needs to be passed to the form, so:
product = Products.objects.get(id=id)
form = ProductForm(instance=product)
if request.method == 'POST':
form = ProductForm(request.POST, request.FILES, instance=product)
# ^^^ Add this
Otherwise without instance, the form will work as if you are trying to create a new object

Why isn't this creating the models in batch?

I am trying to create the object blank in a batch but it is only creating one object after I fill in the form, could anyone help me with what I am doing wrong?
html
{% block content %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Air Ticket Sales</h1>
{{ form }}
batch size:
<input type="number" name="batch" value="{{ batch }}">
<input type="submit" name="" value="Create Blank">
</form>
{% endblock %}
model
class blank(models.Model):
#an integer field that automatically increments by itself as the object are created
number = models.AutoField(primary_key=True)
type = models.CharField(max_length=50, choices=type_choices, default='green')
is_sold = models.BooleanField(default=False)
is_refunded = models.BooleanField(default=False)
date = models.DateField(auto_now_add=True)
date.editable = True
advisor = models.ForeignKey(
User,
models.SET_NULL,
blank=True,
null=True,
)
view
def create_blanks(request):
if request.method == 'POST':
#initializes the data from the form to the value form
form = blank_form(data=request.POST)
batch = request.POST.get("batch", "")
if form.is_valid():
for b in batch:
form.save()
return render(request, "create_blanks.html")
else:
return render(request, "create_blanks.html")
else:
form = blank_form
return render(request, "create_blanks.html", {'form':form})
Yep just found the solution with your help I don't think it is the most efficient or the cleanest one but here you go
for b in range(int(batch)):
form.save()
form.instance = None
form = blank_form(data=request.POST)

Django Requiring Optional Form Field Error

To new readers: Neverwalkaloner's solution solved the initial error but the photo upload is still required and making required false in forms.py gives me a MultiValueDictKeyError. Any help on making it optional would be greatly appreciated.
I have a model and form to upload either a picture and text, or just text. My intention, actually was to make it a choice between an image, text or both and any help with that would be appreciated, but I digress. Uploading only works when an image is included, if it is just text, I get the error:
The view lesyeux.views.posts didn't return an HttpResponse object. It
returned None instead.The view lesyeux
My model is:
class Post(models.Model):
image = models.ImageField(upload_to='uploaded_images', blank=True,
null=True)
text_post = models.CharField(max_length=1000)
author = models.ForeignKey(User)
My form is:
class PostForm(forms.ModelForm):
image = forms.FileField(label='Select an image file',
help_text='Please select a photo to upload')
text_post = forms.CharField(help_text="Please enter some text.")
class Meta:
model = Post
fields = ('image', 'text_post',)
exclude = ('author',)
My view is:
def posts(request, id=None):
neighborhood = get_object_or_404(Neighborhood, id=id)
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = Post(image = request.FILES['image'])
post = form.save(commit=False)
post.author = request.user
post = post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
else:
form = PostForm()
posts = Post.objects.all().order_by('-id')
return render(request, 'posts.html', context = {'form':form,
'posts':posts, 'neighborhood':neighborhood})
and my form is:
<form id="PostForm" method="post" action="/view/{{ neighborhood.id }}/posts/" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="submit" name="submit" value="Post" />
</form>
Your view doesnt return response if form is not valid. To fixt it rewrite view like this:
def posts(request, id=None):
neighborhood = get_object_or_404(Neighborhood, id=id)
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = Post(image = request.FILES['image'])
post = form.save(commit=False)
post.author = request.user
post = post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
else:
form = PostForm()
posts = Post.objects.all().order_by('-id')
return render(request, 'posts.html', context = {'form':form, 'posts':posts, 'neighborhood':neighborhood})

Handle multiple modelforms in one html form

A user will have photos which will be related with their specific album.
So this was the model for that:
class Album(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
update = models.DateTimeField(auto_now_add=False, auto_now=True)
class Photo(models.Model):
photo_privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
user = models.ForeignKey(User)
caption = models.TextField()
image = models.ImageField(upload_to=get_upload_file_name)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
Views.py:
def create_album(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
pform = AlbumPhotoForm(request.POST, request.FILES)
aform = AlbumForm(request.POST)
p_valid = pform.is_valid()
a_valid = aform.is_valid()
if p_valid and a_valid:
photo = pform.save(commit=False)
album = aform.save(commit=False)
photo.user = user
album.user = user
album.save()
photo.album = album
photo.save()
return HttpResponseRedirect('/'+user.username+'/photos')
else:
return render(request, 'create_album.html',{
'pform':pform,
'aform':aform
})
else:
pform = AlbumPhotoForm()
aform = AlbumForm()
return render(request, 'create_album.html', {
'pform':pform,
'aform':aform
})
And the form:
<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ aform.as_p }}
{{ pform.as_p }}
<input type="submit" value="Create and Upload Album"/>
</form>
This works fine if I only have to upload one file (photo) with that form.
Update:
However what I want to do is, show minimum of three input for uploading photos to the new album:
<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ aform.as_p }}
{{ pform.as_p }}
{{ pform.as_p }}
{{ pform.as_p }}
<input type="submit" value="Create and Upload Album"/>
</form>
When doing so, only the last pform is gets saved. And the other two pform's are ignored. How do I get to save all the three forms of photo (pform) accordingly?
Or is there any other way around? Your help will be much appreciated! Thank you.
Use formsets. They do exactly what you want:
from django.forms.models import formset_factory
PhotoFormSet = formset_factory(AlbumPhotoForm, can_delete=False,
min_num=1, validate_min=True,
max_num=3, validate_max=True,
extra=3)
def create_album(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
form = AlbumForm(request.POST)
formset = PhotoFormSet(request.POST, request.FILES)
if all([form.is_valid(), formset.is_valid()]):
album = form.save(commit=False)
album.user = user
album.save()
for photo_form in formset:
if photo_form.cleaned_data:
photo = photo_form.save(commit=False)
photo.album = album
photo.user = user
photo.save()
return redirect('/%s/photos' % user.username )
else:
form = AlbumForm()
formset = PhotoFormSet()
return render(request, 'create_album.html',
{'form': form, 'formset': formset})
And template may look like this:
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<table>
{{ formset }}
</table>
<input type="submit" value="Create and Upload Album"/>
</form>

django hidden field error

i'm building a message system for a virtual community, but i can't take the userprofile id
i have in views.py
def save_message(request):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.sender = request.user
u = UserProfile.objects.get(request.POST['userprofile_id'])
new_obj.owner = u
new_obj.save()
return HttpResponseRedirect('.')
else:
form = MessageForm()
return render_to_response('messages/messages.html', {
'form': form,
},
context_instance=RequestContext(request))
and the template:
{% block primary %}
<form action="." method="post">
{{ form.as_p }}
<p><input type="hidden" value="{{ userprofile.id }}" name = "owner" /></p>
<p><input type="submit" value="Send Message!" /></p>
</form>
{% endblock %}
forms.py:
class MessageForm(ModelForm):
class Meta:
model = Messages
fields = ['message']
models.py:
class Messages(models.Model):
message = models.CharField(max_length = 300)
read = models.BooleanField(default=False)
owner = models.ForeignKey(UserProfile)
sender = models.ForeignKey(User)
I don't figure out why i get this error,since i'm just trying to get the profileId of a user, using a hiddeen field.
the error is:
Key 'UserProfile_id' not found in <QueryDict: {u'owner': [u''], u'message': [u'fdghjkl']}>
and i'm getting it after i fill out the message text field.
Thanks!
it should be
u = UserProfile.objects.get(request.POST['owner'])
because the input's name is 'owner!!
Can you set raise(raise Exception,request.POST) before string: u = UserProfile.objects.get(request.POST['userprofile_id'])
And show me output.