I use this form for adding and updating posts. When I want to edit post and update image Django adds ['image-clear'] checkbox if post has image. But it doesn`t work. Form is not valid, if I tick checkbox and choose new image.But if I only choose new image (without tick checkbox) it works.
I was looking for a long time in what the problem, but I did not find. Can you help me? And sorry for my English
forms.py
class AddIdeaFrom(forms.ModelForm):
class Meta:
model = Idea
fields = ['title', 'description', 'image']
title = forms.CharField(max_length=500, widget=forms.TextInput(attrs={'class': 'form-control'}))
description = forms.CharField(max_length=500, widget=forms.Textarea(attrs={'class': 'form-control'}))
image = forms.FileField(required=False)
views.py
def idea_edit(request,idea_id):
if request.method == "GET":
idea = Idea.objects.get(id=idea_id)
edit_idea = AddIdeaFrom(initial={'title':idea.title,'description':idea.description,'image':idea.image})
return render(request, 'myidea/my/idea_edit.html', {'form':edit_idea, 'comment':idea.comment})
if request.method == "POST":
idea = Idea.objects.get(id=idea_id)
edit_idea = AddIdeaFrom(request.POST,request.FILES)
if edit_idea.is_valid():
edit_idea = AddIdeaFrom(request.POST, request.FILES, instance=idea)
if edit_idea.has_changed():
new_idea = edit_idea.save()
new_status = Status.objects.get(name = STATUS_REVIEW)
new_idea.status = new_status
new_idea.save()
return redirect('/')
else:
return HttpResponse('Need some changes')
else:
form = AddIdeaFrom(instance= idea)
return render(request, 'myidea/my/idea_edit.html', {'form': form})
html
<form method="post" class="post-form" enctype="multipart/form-data">
{% csrf_token %}
<label for="description.for_label" class="col-sm-9">Text</label>
{{ form.description }}
<label for="description.for_image" class="col-sm-9">Choose Image</label>
{{ form.image }}
<button type="submit" class="btn btn-space mb-">Add</button>
</div>
</form>
</div>
From your comment it looks you have problem with contradictory data in your form. It is probably because of using "Clear" checkbox with FileField widget. Try this in your forms.py:
image = forms.FileField(widget=FileInput, required=False)
This should remove "Clear" checkbox from your form.
Or if you don't want let user clear image you can unselect it in view before validation.
Related
I already found many answers to that question but most of them refer to adding request.FILES wchich doesn't work for me. I can upload an image via admin page, but when it comes to form i am getting an error that image is not loaded (while it is)
Here is my model
class Player(models.Model):
name = models.CharField(max_length=30)
surname = models.CharField(max_length=30)
position = models.ForeignKey(Position,on_delete=models.CASCADE)
shirt_number = models.IntegerField()
team = models.ForeignKey(Team,null=True,on_delete=models.SET_NULL)
image = models.ImageField(upload_to='images/players/')
Here is my form
class PlayerForm(forms.ModelForm):
class Meta:
model = Player
exclude = ('team',)
Here is views.py
def team_detail(request,slug):
team = get_object_or_404(Team, slug=slug)
players = Player.objects.filter(team_id=team.id)
if request.method == "POST":
form = PlayerForm(request.POST,request.FILES)
if form.is_valid():
form.save()
return redirect('')
else:
form = PlayerForm()
return render(request,'team_detail.html',{'team':team,'players':players,'form':form})
And here is template file
<form method = "POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="SUBMIT">
</form>
Before submitting
After pressing submit button
You need to specify the enctype="…" attribute [mdn] to encode the file properly:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="SUBMIT">
In the view you will also need to specify a value for the Team of the instance you create:
def team_detail(request,slug):
team = get_object_or_404(Team, slug=slug)
if request.method == 'POST':
form = PlayerForm(request.POST, request.FILES)
if form.is_valid():
form.instance.team = team
form.save()
return redirect('name-of-some-view')
else:
form = PlayerForm()
players = Player.objects.filter(team=team)
return render(request,'team_detail.html', {'team':team,'players':players,'form':form})
so I encountered this problem with Django and ModelForms. Everything loads as expected but when I'm trying to send data by hitting Enter nothing happens.
models.py
class Drinks(models.Model):
name = models.CharField(max_length=50)
number = models.DecimalField(decimal_places=2, max_digits=2000)
def __str__(self):
return self.name
forms.py ( I tried with list and tuple as well )
class DrinksForm(forms.ModelForm):
class Meta:
model = Drinks
fields = [
'name',
'number'
]
views.py
def DrinksView(request):
form = DrinksForm(request.POST or None)
if form.is_valid():
print("VALIDATION COMPLETE")
form.save()
form = DrinksForm()
return render (request, 'form2.html', { 'form' : form })
template.html
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
admin.py
from django.contrib import admin
from .models import Drinks
admin.site.register(Drinks)
I did all necessary migrations.
Any Ideas what im doing wrong?
Your form doesn't have a submit button:
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
For your view, consider this instead:
def new_drink_view(request):
if request.method == "POST":
form = DrinksForm(request.POST)
# check if valid
# ...
else:
form = DrinksForm()
return render (request, 'form2.html', { 'form' : form })
Be sure to import the DrinksForm form.
In my django project I have a form VisitorRegForm which collects scanned_id and body_temp and submits data to my database table ClinicalData, since the current user is already logged in, how can I make this form to also be able grab current logged in user's username and email (Note: username and email were both created from the built-in django User model) and submit these four items: 'scanned_id', 'body_temp', 'username', 'email' into the database table ClinicalData?
Don't mind the missing details and inports, the form works and am able to submit 'scanned_id', 'body_temp'. Help me on the easiest way I will be able to submit these four items: 'scanned_id', 'body_temp', 'username', 'email' looking at the details shown in the files below:
Where should it be easier to achieve this; in the views.py or the template file?
forms.py
class VisitorRegForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class ScannerForm(ModelForm):
class Meta:
model = ClinicalData
fields = ['scanned_id', 'body_temp']
models.py
class ClinicalData(models.Model):
...
scanned_id = models.CharField(verbose_name="Scanned ID", max_length=50, null=True)
body_temp = models.DecimalField(verbose_name="Body Temperature", max_digits=3, decimal_places=1, null=True)
username = models.CharField(verbose_name="Facility Name", max_length=200, null=True)
email = models.EmailField(verbose_name="Visitor Email", max_length=200, null=True)
...
views.py
Am assuming I might need like two variables here in the views that should help me like the ones i've commented out, if it should start from here, help me how it should succeed:
#login_required(login_url='login')
def scanEnter(request):
#grab_username = function_to_grab_current_logged_in_username_HELP_ME_HERE
#grab_email = function_to_grab_current_logged_in_user_email_HELP_ME_HERE
form = ScannerForm(request.POST)
if request.method == 'POST':
form = ScannerForm(request.POST)
if form.is_valid():
form.save()
return redirect('scanenter')
context = {'form': form}
return render(request, 'scan_enter_fac.html', context)
scan_enter_fac.html
<form action="" method="post">
{% csrf_token %}
<div class="">scanned_id<input type="text" id="multiple" class="form-control" placeholder="or Type ID here; e.g: ACCTS-147" name="scanned_id"></div>
<div class="">body_temp<input type="text" class="form-control" placeholder="e.g: 36.5" name="body_temp"></div>
<button type="submit" class="btn btn-danger btn-block">Submit</button>
</form>
views.py:
#login_required(login_url='login')
def scanEnter(request):
#grab_username = function_to_grab_current_logged_in_username_HELP_ME_HERE
#grab_email = function_to_grab_current_logged_in_user_email_HELP_ME_HERE
form = ScannerForm(request.POST)
if request.method == 'POST':
form = ScannerForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.username = request.user.username #new
form.email = request.user.email #new
form.save()
return redirect('scanenter')
context = {'form': form}
return render(request, 'scan_enter_fac.html', context)
scan_enter_fac.html
<form action="" method="post">
{% csrf_token %}
<div class="">{{ form.scanned_id }}</div>
<div class="">{{ form.body_temp }}</div>
<button type="submit" class="btn btn-danger btn-block">Submit</button>
</form>
I'm currently working on a personal project where in a page (purchases page), there will be the main form (includes product name, product category and product specifications fields).
now, there is a link "Add New Product Category" that activates the modal. This modal includes a separate form.
What you are seeing is the final output or what I want the page to be, i only did that in html, no django coding involve.
My (stupid) question is, how am i going to display BOTH forms? I don't understand how {{form}} works.
I successfully rendered the productCategoryForm in the modal by using the code {{form}} but when I do the same in the second form productDetailsForm it's not rendering or displaying. It's blank. I'm not sure how is this going to work.
Below is my Views.py and Forms.py codes.
Views.py
def addNewProduct(response):
c_form = productCategoryForm(response.POST)
p_form = productDetailsForm(response.POST)
if response.method == "POST":
if c_form.is_valid():
a = c_form.cleaned_data["productCategField"]
b = productCategoryModel(productcategoryCol=a)
b.save()
return HttpResponseRedirect("/acctg/purchases/")
if p_form.is_valid():
c = p_form.cleaned_data["productNameField"]
d = productModel(productnameCol=c)
d.save()
return HttpResponseRedirect("/acctg/purchases/")
context = {
"p_form": p_form,
"c_form": c_form
}
return render(response, 'purchases.html', context)
Forms.py
class productCategoryForm(forms.Form):
productCategField = forms.CharField(label="Product Category", max_length=100, widget= forms.TextInput(attrs={'class':'form-control col-sm-8 col-form-label'}))
class productDetailsForm(forms.Form):
productNameField = forms.CharField(label="Product Name", max_length=100, required=True, widget=forms.TextInput(attrs={'placeholder':'Enter Product Name', 'class':'form-control col-sm-8 col-form-label'}))
Models.py
# Create your models here.
class productCategoryModel(models.Model):
productcategoryCol = models.TextField()
def __str__(self):
return self.productcategoryCol
class productModel(models.Model):
productnameCol = models.TextField()
productspecsCol = models.TextField()
#productcategCol = models.ForeignKey(productcategoryCol, default=None, on_delete=models.CASCADE)
def __str__(self):
return self.productnameCol
Appreciate your help on this. Thank you!
You can pass both forms in your template through context.
def addNewProduct(request):
p_form = productDetailsForm()
c_form = productCategoryForm()
if request.method == "POST":
p_form=productDetailsForm(request.POST)
if p_form.is_valid():
p_form.save()
return redirect("/")
context = {
"p_form": p_form,
"c_form": c_form
}
return render(response, 'purchases.html', context)
Now in the template you can render both forms with {{p_form}} and
{{c_form}}. And provide different actions and different views for both forms.
EDIT:
If you want to handle both forms with a single view then you can use the name attribute in your submit button inside your template.
template:
<form method='POST'>
{{p_form.as_p}}
<button type="submit" name="btn1">Add Product</button>
</form>
<form method='POST'>
{{c_form.as_p}}
<button type="submit" name="btn2">Add Category</button>
</form>
Now in the views.
def addNewProduct(request):
p_form = productDetailsForm()
c_form = productCategoryForm()
if request.method=='POST' and 'btn1' in request.POST:
p_form=productDetailsForm(request.POST)
if p_form.is_valid():
p_form.save()
return redirect("/")
if request.method=='POST' and 'btn2' in request.POST:
c_form=productCategoryForm(request.POST)
if c_form.is_valid():
c_form.save()
return redirect("/")
context = {
"p_form": p_form,
"c_form": c_form
}
return render(response, 'purchases.html', context)
To avoid spaghetti code I usually separate the views:
# views.py
def purchases(response):
form = productCategoryForm()
detailsForm = productDetailsForm()
return render(response, 'purchases.html', {"form": form, "detailsForm": detailsForm})
#require_POST
def add_category(request):
form = productCategoryForm(response.POST)
if form.is_valid():
a = form.cleaned_data["productCateg"]
b = productCategory(productCat=a)
b.save()
return HttpResponseRedirect("/acctg/purchases/")
#require_POST
def add_product_details(request):
form = productDetailsForm(response.POST)
if form.is_valid():
# your logic here
b.save()
return HttpResponseRedirect("/acctg/purchases/")
# urls.py
path('purchases/', purchases, name='purchases'),
path('add_category/', add_category, name='add_category'),
path('add_product_details/', add_product_details, name='add_product_details'),
# purchases.html
<form action="{% url 'add_category' %}" method="post">
{% csrf_token %}
{{form}}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<form action="{% url 'add_product_details' %}" method="post">
{% csrf_token %}
{{detailsForm}}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
I have a django form, but it's not showing the "upload file" field when I render it on my website. What am I doing wrong? Ideally, the form has a question ID associated with it that's submitted automatically (e.g. it doesn't have to be manually put in by the user when uploading the file)
models.py
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
response_file = models.FileField(upload_to='audio_responses')
forms.py
class PostAudio(forms.ModelForm):
class Meta:
model = Choice
fields = ('response_file',)
views.py
def QuestionRecordSubmitView(request, pk):
model = Question
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.instance.question_id = pk
form.save()
# get survey pk
question_instance = Question.objects.get(pk=pk)
survey_pk = question_instance.survey.pk
return redirect('survey-share',pk=survey_pk)
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html')
html
{% extends "landing/base.html" %}
{% block content %}
<h2>New Submission</h2>
<form method="POST" class="post-form" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock content %}
def QuestionRecordSubmitView(request, pk):
model = Question
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.instance.question_id = pk
form.save()
# get survey pk
question_instance = Question.objects.get(pk=pk)
survey_pk = question_instance.survey.pk
return redirect('survey-share',pk=survey_pk)
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html', {'form':form})```