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})```
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})
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 view like:
def some_view(request, page_url):
form = UserTicketForm(request.POST)
if request.method == 'POST':
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
data = dict(
form=UserTicketForm,
)
return render(request, 'front/some_page.html', data)
and in HTML page it has:
{% csrf_token %}
{% bootstrap_form form %}
{% block submit %}
<div class="button_holder">
<button type="submit" name="register-submit" class="btn btn-primary" value="send">
submit
</button>
</div>
{% endblock %}
each time I refresh the page, it resubmits the last submitted form. how can fix this issue?
You need to redirect to a different url after the form is submitted and saved
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
return HttpResponseRedirect(reverse('some_url'))
Write Like this
def some_view(request, page_url):
if request.method == 'POST':
form = UserTicketForm(request.POST)
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
data = dict(
form=UserTicketForm,
)
return render(request, 'front/some_page.html', data)
i am trying to filter a forms drop down list based on a users group
To find the user group i am using a custom templatetag
template tag
from django import template
register = template.Library()
#register.filter(name='in_group')
def in_group(user,group_name):
try:
group=Group.objects.get(name=group_name)
except Group.DoesNotExist:
return False
return group in user.groups.all()
task.html
{% load group_check %}
<form method="post">
{% csrf_token %}
{% if user.is authenticated %}
{% if requset.user|in_group:'DEVELOPER' %}
#...DO SOMETHING
{{ form.as_p }}
<button type="submit">add task</button>
</form>
models
GOALS_TYPE= (('DT','Daily Task'),
('WT','Weekly Task'),
('V','Verified'),
('D','Done'),
)
class GoalStatus(models.Model):
title = models.CharField(max_length=254, null=True)
task_id=models.IntegerField(default=1,null=False)
description =models.CharField(max_length=254)
verified_by=models.ForeignKey('ScrumyUser', on_delete= models.CASCADE, null=True)
status=models.CharField(choices=GOALS_TYPE, max_length=2, default='DT')
def __str__(self):
return self.title
the template for the form is based on the forms.py
forms.py
class ChangeTaskForm(forms.ModelForm):
class Meta:
model = GoalStatus
fields = ('title', 'task_id','description','status', 'verified_by')
views.py
def move_goals(request,pk):
if request.method == 'POST':
form = ChangeTaskForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/index/')
else:
form = ChangeTaskForm()
return render(request, 'oderascrumy/task.html', {'form': form})
urls.py
path('task/<pk>/', views.move_goals, name='move_goals')
so for example if the user is in group "developer", the drop down choices for status will be only verified and done
You can do like below
views.py
def move_goals(request,pk):
if request.method == 'POST':
form = ChangeTaskForm(request.POST, user=request.user)
if form.is_valid():
return HttpResponseRedirect('/index/')
else:
form = ChangeTaskForm(user=request.user)
return render(request, 'oderascrumy/task.html', {'form': form})
forms.py
class ChangeTaskForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ChangeTaskForm, self).__init__(*args, **kwargs)
if user.groups.filter(name='DEVELOPER').exists():
self.fields['status'].choices = (('V','Verified'), ('D','Done'),)
class Meta:
model = GoalStatus
fields = ('title', 'task_id','description','status', 'verified_by')
template.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">add task</button>
</form>
I think no need of template tag for this.
Please, help.. I do not udersatand what I should do this code to work..
home.html:
<form class="subscribe-form" action="{% url 'subscribe' %}" method="POST">{% csrf_token %}
{{ form }}
<button class="btn btn-main btn-lg" type="submit">Подписаться!</button>
</form>
{% if success %}
<div class="subscribe-result">
{{ success }}
</div>
{% endif %}
urls.py:
url(r'^$', 'interior_app.views.home', name='home'),
url(r'^subscribe/$', 'interior_app.views.subscribe', name='subscribe')
models.py:
class Subscriber(models.Model):
email = models.EmailField('', max_length=100, null=True, blank=True)
forms.py:
class SubscriberForm(forms.ModelForm):
class Meta:
model = Subscriber
fields = ['email']
admin.py:
class SubscriberAdmin(admin.ModelAdmin):
list_display = ('email',)
admin.site.register(Subscriber, SubscriberAdmin)
views.py:
def home(request):
portfolios = PortfolioObject.objects.all()
photos = []
for portfolio in portfolios:
for obj in portfolio.photo_set.all():
photos.append(obj)
form = SubscriberForm()
context = {"photos": photos[::2], "form": form}
return render(request, "home.html", context)
def subscribe(request):
print request
success = ''
if request.method == "POST":
print request.POST
form = SubscriberForm(request.POST)
print form
if form.is_valid():
form.save()
success = "Ваш Email успешно отправлен"
form = SubscriberForm()
else:
form = SubscriberForm()
context = {"photos": photos[::2], "form": form, "success": success}
return render(request, "home.html", context)
I input email in the form, push button and nothing is happening.
Any data in admin, any {{ success }}.
I need not AJAX.. I would like to do this feature only with Django