Form.is_valid() always returns false. Here's my code.
#urls.py
url(r'^create/', "app.views.createpost", name="createpost"),
My models.py
class Post(models.Model):
"""docstring for Post"""
post_image = AjaxImageField(upload_to='posts', max_width=200, max_height=200, crop=True, null= False, default='site_media/media/BobMarley/bob1.jpg')
poster = models.ForeignKey(User, null= False, default=User.objects.get(username="admin")
Here's my forms.py
#forms.py
class AjaxImageUploadForm(forms.Form):
image = forms.URLField(widget=AjaxImageWidget(upload_to='posts'))
view.py
#views.py
def createpost(request):
if request.method == 'POST':
form = AjaxImageUploadForm(request.POST, request.FILES)
if form.is_valid():
newpost = Post(post_image = request.FILES['image'])
newpost.poster = request.user
newpost.save()
return HttpResponseRedirect('/create/')
else:
form = AjaxImageUploadForm() # An empty, unbound form
posts = Post.objects.all()
return render_to_response('create.html',{'posts': posts, 'form': form},context_instance=RequestContext(request))
The Template
#create.html
{% block extra_head %}
{{ form.media }}
{% endblock %}
{% block body %}
<form method="POST" enctype="multipart/form-data" action="{% url "createpost" %}">
{% csrf_token %}
{{ form.errors}}
{{ form.as_p }}
<button type="submit" name='image'>Upload</button>
</form>
{% endblock %}
The form is never valid and the error printed is "This field is required."
And this is the form widget begin created
<tr><th><label for="id_image">Image:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul>
<div class="ajaximage"><a class="file-link" target="_blank" href=""> <img class="file-img" src=""></a> <a class="file-remove" href="#remove">Remove</a>
<input class="file-path" type="hidden" value="" id="id_image" name="image" /> <input type="file" class="file-input" name="image"/> <input class="file-dest" type="hidden" name="image" value="/ajaximage/upload/posts/0/0/0"> <div class="progress progress-striped active"> <div class="bar"></div></div>
</div>
</td></tr>
I am using the django package called django-ajaximage and their custom widget (AjaxImageWidget) is probably a custom text widget
class AjaxImageWidget(widgets.TextInput):
Thank you for you help
You do not need the init on your model class. Also, null=False is the default. I'm not sure the text 'admin' will default to the user with username admin. You would need to do:
default=User.objects.get(username="admin")
You can also include the poster assignment in the creation of the object like so:
newpost = Post(post_image=request.FILES['image'], poster=request.user)
To make the form validate you need to put blank=True in the field like so:
poster = models.ForeignKey(User, blank=True, default=User.objects.get(username="admin")
I would also make the form be a ModelForm:
class AjaxImageUploadForm(forms.ModelForm):
class Meta:
model=Post
exclude=['poster',]
Related
I have a form so an user can ask for a loan and it will tell them if it´s approved or not. The problem is not the logic, it´s the submit input that doesn't work. It will not save the form in the database or show me the errors because of the submit input. Maybe is something wrong with the succes_url? I don't know, but here's my code:
views.py:
#don't worry about the logic part of the form, it's just to show how it´s supposed to work
class LoanRequest(LoginRequiredMixin, generic.CreateView):
form_class = LoanForm
success_url = reverse_lazy('Prestamos')
template_name = 'Prestamos/template/Prestamos/prestamos.html'
def form_valid(self, form):
user = self.request.user
cliente = Cliente.objects.get(user_id = user.id)
if not cliente.approve_loan(form.cleaned_data.get('loan_total')):
form.add_error(field=None, error='loan not approved')
return self.form_invalid(form)
else:
form.instance.customer_id = cliente
super(LoanRequest, self).form_valid(form)
return render(self.request, 'Prestamos/template/Prestamos/prestamos.html', context={'form': form, 'success_msg': 'loan approved!'})
urls.py:
urlpatterns = [
path('prestamos/', views.LoanRequest.as_view(), name = 'prestamos'),
]
forms.py:
class LoanForm(forms.ModelForm):
class Meta:
model = Prestamo #loan in English
fields = ['loan_type', 'loan_total', 'loan_date']
and the template:
<div class="container">
{%if success_msg%}
<p class="alert alert-success">{{success_msg}}</p>
{%endif%}
<form action="" method="POST">
{%csrf_token%}
{%for field in form%}
<div class="form-group">
<label for="{{field.label}}">{{field.label}}</label>
{{field}}
</div>
{%for error in field.errors%}
<p>{{error}}</p>
{%endfor%}
{%endfor%}
<input type="submit" value="request"></input>
</form>
</div>
models.py:
class Prestamo(models.Model):
loan_id = models.AutoField(primary_key=True)
loan_type = models.CharField(max_length=20,
choices = [('PERSONAL', 'PERSONAL'), ('HIPOTECARIO', 'HIPOTECARIO'), ('PRENDARIO', 'PRENDARIO')])
loan_date = models.DateField()
loan_total = models.IntegerField()
customer_id = models.IntegerField()
class Meta:
db_table = 'prestamo'
Well, <input> is an empty tag, it does not contain anything, so don't close it.
Additionally, I'd recommend you to make gaps between template tags, like it should be {% endfor %} not {%endfor%}.
Also, remove the empty action attribute from form, as Django always take current page route if not mentioned or empty string.
Also use novalidate on form for rendering custom errors.
Try this template:
<div class="container">
{% if success_msg %}
<p class="alert alert-success">{{success_msg}}</p>
{% endif %}
<form method="POST" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{field.label}}">{{field.label}}</label>
{{field}}
</div>
{% for error in field.errors %}
<p>{{error}}</p>
{% endfor %}
{% endfor %}
<input type="submit" value="request">
</form>
</div>
Edit:
One mistake I could see the name for the view is prestamos and you have mentioned it as Prestamos, which is wrong.
So:
class LoanRequest(LoginRequiredMixin, generic.CreateView):
form_class = LoanForm
success_url = reverse_lazy('prestamos')
template_name = 'Prestamos/template/Prestamos/prestamos.html'
I am building a Blog App and I am working on a feature in which A user can report comment so I created another model for storing reports so i am saving which comment is reported But I placed report form in detail view so report form will be below the comment in post detail page, In which I am not getting the comment id when reporting.
models.py
class Blog(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=1000)
class Comment(models.Model):
commented_by = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.CharField(max_length=1000)
class ReportComment(models.Model):
reported_by = models.ForeignKey(User, on_delete=models.CASCADE)
reported_comment = models.ForeignKey(Comment, on_delete=models.CASCADE)
text = models.CharField(max_length=1000)
views.py
def blog_detail_page(request, blog_id):
post = get_object_or_404(Blog, pk=blog_id)
if request.method == 'POST':
reportform = CommentReportForm(data=request.POST)
if FlagCommentForm.is_valid():
form = reportform.save(commit=False)
# Saving in this line
flagForm.reported_comment = reportform.id
form.reported_by = request.user
form.save()
return redirect('home')
else:
reportform = CommentReportForm()
context = {'reportform':reportform, 'post':post}
return render(request, 'blog_detail_page.html', context)
blog_detail_page.html
{{post.title}}
{% for comment in post.comment_set.all %}
{{comment.body}}
<div class="container">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ reportform }}
</table>
<button type="submit">Save</button>
</form>
</div>
{% endfor %}
What have I tried :-
I have also tried by using loop like :-
comments = post.comment_set.all()
for com in comments:
if request.method == 'POST':
......
if reportform.is_valid():
....
......
......
form.reported_by = com
But it always saved the first comment id.
Then I tried by request.POST method, Like :-
comment_ID = request.POST['comment_id']
But is showed MultiValueDictKeyError error.
I have tried many times But the id of comment is not saving with report instance.
You will need to add the primary key of the comment to the form, or to the URL where you submit the form to. For example as a hidden form element:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="comment_id" value="{{ comment.pk }}">
<table>
{{ reportform }}
</table>
<button type="submit">Save</button>
</form>
An alternative is to make a URL where you report a comment to with:
urlpatterns = [
path('comment/<int:comment_id>/report', some_view, name='report-comment')
]
then you can submit the form to that view with:
<form method="post" action="{% url 'report-comment' comment_id=comment.pk %}" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ reportform }}
</table>
<button type="submit">Save</button>
</form>
I have a form where I would like to have a username and production line send along. The thing is that the username should be taken from current logged user (and viewed as uneditable field) but the production line should be selected via dorpdown.
It works by somehow since when I click on "User" dropdown it shows only the logged user.
views:
def order(request):
storage = PartNumber.objects.all()
username = request.user.username
if request.method == 'POST':
order_form = OrderForm(username=username, data=request.POST)
if order_form.is_valid():
order_form.save()
return redirect('order')
elif request.method == 'GET':
order_form = OrderForm(username=username)
return render(request, 'dashboard/order.html', {"form": order_form, "username": username})
forms:
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ('end_user_id', 'production_line_id')
def __init__(self, *args, **kwargs):
username = kwargs.pop('username', None)
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['end_user_id'].queryset = User.objects.filter(username=username)
models:
class Order(models.Model):
end_user_id = models.ForeignKey(User, on_delete=models.CASCADE)
production_line_id = models.OneToOneField(ProductionLine, on_delete=models.CASCADE)
date_ordered = models.DateTimeField(auto_now_add=True, null=True)
date_completed = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return str(self.status)
html:
{% extends 'dashboard/main.html' %}
{% load static %}
{% load bootstrap %}
{% block content %}
<h3>Zamowienie</h3>
<br>
<!--{{ form|bootstrap }}-->
<form role="form" action="" method="post">
{% csrf_token %}
<div class="form-group">
<label>Uzytkownik </label>
<!--<input class="form-control" placeholder="{{user}}" readonly>-->
{{ form.end_user_id }}
</div>
<br>
<div class="form-group">
<label>Linia produkcyjna </label>
{{ form.production_line_id }}
</div>
<br>
<div class="text-center">
<button type="submit" class="btn btn-primary">Przeslij</button>
</div>
</form>
{% endblock content %}
Now if you look at the html above, the commented line :
<!--<input class="form-control" placeholder="{{user}}" readonly>-->
actually gives me the look I want but doesn't send the username (doesn't work)
I was trying different solutions from different posts that I found here but nothing seems to work for me.
Any ideas ?
You are passing username to the template using the variable username.
In the template you are trying to get the username by using the variable user.
<input class="form-control" placeholder="{{user}}" readonly>
Should be :
<input class="form-control" placeholder="{{username}}" readonly>
I am working on my first Django project.
But I get following errors:
edit_file template
<form method="POST" action="{% url 'edit_file' file.id %}">
{% csrf_token %}
{{ form.errors }}
{{ form.non_field_errors }}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field.errors }}
{{ hidden_field }}
{% endfor %}
<div class="form-group row">
<label for="id_name" class="col-sm-3 col-form-label"> File Name </label>
<div class="col-sm-4">
{% render_field form.name|add_class:"form-control" %}
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">File Path</label>
<div class="col-sm-4">
{% render_field form.directory_path|add_class:"form-control" %}
</div>
</div>
<div class="form-group">
{% render_field form.script_code|add_class:"form-control" %}
<pre id="id_script_code" style="height: 40pc;">{{ form.script_code }}</pre>
</div>
<button type="submit" class="btn btn-success mr-2">Save Changes</button>
Back
</form>
Views.py
def edit_file(request, id):
instance = get_object_or_404(File, id=id)
if request.method == "POST":
form = EditFileForm(request.POST, instance=instance)
if form.is_valid():
print('Form validation => True')
form.save()
return HttpResponse('<h1> database updated! </h1>')
else:
print('Form validation => False')
file = File.objects.latest('id')
context = {'file': file, "form": form}
return render(request, 'edit_file.html', context)
else:
instance = get_object_or_404(File, id=id)
form = EditFileForm(request.POST or None, instance=instance)
file = File.objects.latest('id')
context = {'file': file, "form": form}
return render(request, 'edit_file.html', context)
forms.py
class EditFileForm(ModelForm):
# field_order = ['field_1', 'field_2']
class Meta:
print("forms.py 1")
model = File
fields = ('name', 'script_code', 'directory_path','version')
def clean(self):
print("forms.py 2")
cleaned_data = super(EditFileForm, self).clean()
name = cleaned_data.get('name')
print("cleaned data: ", cleaned_data)
Models:
Version id point to a version which contains multiple files.
class File(models.Model):
# Incrementing ID (created automatically)
name = models.CharField(max_length=40)
script_code = models.TextField() # max juiste manier?
directory_path = models.CharField(max_length=200)
version = models.ForeignKey('Version', on_delete=models.CASCADE)
class Meta(object):
db_table = 'file' # table name
class Version(models.Model):
# Incrementing ID (created automatically)
version_number = models.CharField(max_length=20)
pending_update = models.BooleanField(default=False)
creation_date = models.DateTimeField(auto_now_add=True, null=True, editable=False)
modification_date = models.DateTimeField(auto_now_add=True, null=True)
connecthor = models.ForeignKey('ConnecThor', on_delete=models.CASCADE)
def __str__(self):
return self.connecthor_id
The problem:
form.is_valid() keeps failing. My view returns one error.
*version: This field is required. But I don't know how to fix this. Users should only be able to update 3 of the 5 data fields. So there is no reason to show the PK or FK in the template.
You've included version in the list of fields in your form, but you aren't outputting it in the template so there is no means of providing it. Since the model field does not specify blank=True, it is a required field, hence the error.
If you don't want users to be able to modify this field, you should remove it from that list of fields under Meta.
You do not have version in your template. Your model field for version does not say it can have null values. Hence your form validation fails. Include it in your template or remove the field from EditFileForm class's Meta class in forms.py
Hi i am relatively new to Django. I am currently trying to store values into database. Timesheet.html is basically my form and i have tried to do the validation but it doesn't work. I have searched everything i can but the data being filled out wont be saved into database. Is there anywhere to check that the checkbox has been ticked before user can submit it ?
timesheet.html
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
<input id="sid" type="field" name="studentid">
</div>
</div>
<div class="sub-content">
<div>
<p>Student Name: {{timesheet.studentName}}</p>
<input id="sname" type="field" name="studentname">
</div>
</div>
<div class="sub-content">
<div>
<p>Start Date: {{timesheet.startDate}}</p>
<input id="sdate" type="date" name="startdate">
</div>
</div>
<div class="sub-content">
<div>
<p>End Date: {{timesheet.endDate}}</p>
<input id="edate" type="date" name="enddate">
</div>
</div>
</div>
<div class="end-content">
<div class="center-align">
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
<input id="agree" type="checkbox" name="checkbox" class="tick-att">
</div>
<br>
<div class="align-right">
<input type="submit" class="button" name="submit" value="submit" >
</div>
</div>
</div>
</form>
models.py
class Timesheet(models.Model):
studentID = models.CharField("Student ID", max_length=8, primary_key=True, default="")
studentName = models.CharField("Student Name", max_length=500, default="")
startDate = models.DateField("Start Date", max_length=8)
endDate = models.DateField("End Date", max_length=8)
def __str__(self):
return self.studentID
class TimesheetForm(forms.ModelForm):
class Meta:
model = Timesheet
fields = '__all__'
views.py
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save(commit=False)
timesheet.studentID = request.POST.get('studentID')
timesheet.studentName = request.POST.get('studentName')
timesheet.startDate = request.POST.get('startDate')
timesheet.endDate = request.POST.get('endDate')
timesheet.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
#if the form is not valid, redirect the student to the same page
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
There are lots of very strange things here.
Firstly, there is no need to set the fields manually on save. That is exactly what form.save() does in the first place. (And if you ever did need to set something manually, you should always get it from form.cleaned_data rather than request.POST.)
Secondly, you re-instantiate the form if it fails validation. That means that the users can never see the errors that are preventing it from validating.
Thirdly, you should show errors in the template. Along with that, you should let Django itself output your fields so that they are automatically prepopulated when the form is invalid.
Finally, you should add your checkbox as a field on the form, so that it is validated along with everything else.
class TimesheetForm(forms.ModelForm):
checkbox = forms.BooleanField()
class Meta:
model = Timesheet
fields = '__all__'
...
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
...
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
{{ form.errors }}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
{{ form.studentID }}
</div>
</div>
</div>
.... etc...
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
{{ form.checkbox }}
</div>