I want to save and filter user’s objects in my django app. After inputting the below codes, the imagefield is not uploading any image to my database and it’s not returning any image in my template.
Models
class Fin(models.Model):
user=models.ForeignKey(User)
title=models.CharField(max_length=250, help_text='3 bedroom flat for lease')
main_view=models.ImageField(upload_to="photos",blank=True, null=True)
side_view=models.ImageField(upload_to="photos",blank=True, null=True)
address=models.CharField(max_length=200)
city=models.CharField(max_length=200)
state=models.CharField(max_length=200)
guideline=models.TextField(max_length=1000)
def __unicode__(self):
return self.title
class FinForm(ModelForm):
class Meta:
model=Fin
fields=('title','main_view','side_view', 'address','city','state','guideline')
exclude=('user')
Views
def fincrib(request):
extra_data_context={}
#if there's nothing in the field do nothing.
if request. method=="POST":
form =FinForm(request.POST)
if form.is_valid():
data=form.cleaned_data
newfincribs=Fin(
user= request.user,
title=data['title'],
main_view=data ['main_view'],
side_view=data['side_view'],
address=data['address'],
city=data['city'],
state=data['state'],
guideline=data['guideline'])
newfincribs.save()
extra_data_context.update({'FinForm':form})
else:
form = FinForm()
extra_data_context.update({'FinForm':form})
extra_data_context.update({'Fins':Fin.objects.filter(user=request.user)})
return render_to_response('post.html',extra_data_context,context_instance=RequestContext(request))
Template
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<center> {{FinForm.as_p}} </center>
<input type="submit" value="Submit"/>
</form>
{% for Fin in Fins %}
<tr>
{{Fin.user}} </p> </strong>
<p>{{Fin.title}}</p>
<p><img src="{{MEDIA_URL}}/{{Fin.main_view}}"/></p>
<p> <img src="{{MEDIA_URL}}/{{Fin.side_view}}"/></p>
<p> {{Fin.address}} </p>
<p> {{Fin.city}}</p>
<p> {{Fin.state}}</p>
<p> {{Fin.guideline}}</p>
{% endfor %}
{% endblock %}
You're missing a number of things on the template and view layer.
Read this: https://docs.djangoproject.com/en/1.3/topics/http/file-uploads/#basic-file-uploads
Read binding uploaded files to a form from django official docs. I think it can help.
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 have a models.py with the following fields:
class ChatStream(models.Model):
bot = models.TextField()
user = models.TextField()
name = models.CharField(max_length=100, null=True)
created_date = models.DateTimeField(auto_now_add=True)
And I'd like on a website to iterate through "bot" and "user" one at a time, so the site would hypothetically display something like:
bot: hello!
user: what's up?
bot: I'm good
user: What's your name
bot: bot is my name
.... etc. this would keep going...
So in my views.py I have
def displayDict(request):
m = ChatStream.objects.all()
return render(request, 'chatStream.html',
{"chat": m})
def send(request):
message = request.POST.get('userMessage', False)
ip = visitor_ip_address(request)
response = routes(message, ip)
print(ip, "user sent:", message, "bot response:", response)
chatItem = ChatStream(bot=response, user=message, name=ip)
chatItem.save()
return HttpResponseRedirect('/chat/')
Then in my template, chat.html I have
{% block chatStream %} {% endblock %}
And chatStream.html (this is where the error is happening I believe... how do you iterate through two items in the model so they appear one after the other on the html file?)
{% extends 'chat.html' %}
{% block chatStream %}
{% for a in bot%}
{% for b in user%}
<p>
<b>bot:</b> {{a}} <br>
<b>user:</b> {{b}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}
But this does not work -- no text from the model is displayed on the site. I am not understanding how to iterate through two items within the model at once inside of the chatStream.html.
A lot going on here, lets try to break it down:
First, you need to pass context variables to your templates if you want to render them using the (jinja-like) Django template rendering system.
Your view function for rendering the template would look like this:
views.py
def render_chat_page(request):
# do some logic:
...
# pack the context variables:
context = {
'some_key' : 'some_value',
'chat_streams' : ChatStream.objects.all(),
...
}
return render(request, 'chat_page.html', context=context)
Ok, now that we've passed the context variables to the template, we can render html elements using the variables like so:
template.html
<div> The value of "some_key" is: {{some_key}} </div>
{% for chat_stream in chat_streams %}
<div> user says: {{chat_stream.user}}</div>
<div> bot says: {{chat_stream.bot}}</div>
{% endfor %}
This will render the user and bot messages for each ChatStream object. However my hunch is that this is not entirely what you're after, instead you may want something more dynamic.
In your displayDict view you're passing a QuerySet to the context. So, you need to loop over the QuerySet in your template.
{% extends 'chat.html' %}
{% block chatStream %}
{% for item in chat %}
<p>
<b>bot:</b> {{item.bot}} <br>
<b>user:</b> {{item.user}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}
I have the following models defined:
class Item(models.Model):
rfid_tag = models.CharField()
asset = models.OneToOneField('Assets', default=None, null=True,
on_delete=models.SET_DEFAULT,)
date = models.DateTimeField(name='timestamp',
auto_now_add=True,)
...
class Assets(models.Model):
id = models.AutoField(db_column='Id', primary_key=True)
assettag = models.CharField(db_column='AssetTag', unique=True, max_length=10)
assettype = models.CharField(db_column='AssetType', max_length=150)
...
class Meta:
managed = False
db_table = 'Assets'
ordering = ['assettag']
def __str__(self):
return f"{self.assettag}"
def __unicode__(self):
return f"{self.assettag}"
For which I have created the following form and formset:
class ItemDeleteForm(forms.ModelForm):
asset = forms.CharField(required=True,
help_text= "Item asset tag",
max_length=16,
label="AssetTag",
disabled=True,
)
delete = forms.BooleanField(required=False,
label="Delete",
help_text='Check this box to delete the corresponding item',
)
class Meta:
model = Item
fields = ['asset']
ItemDeleteMultiple = forms.modelformset_factory(model=Item,
form=ItemDeleteForm,
extra=0,
)
managed by the view:
class DeleteMultipleView(generic.FormView):
template_name = '*some html file*'
form_class = ItemDeleteMultiple
success_url = reverse_lazy('*app_name:url_name*')
def form_valid(self, form):
return super().form_valid(form)
And rendered in the template:
{% extends "pages/base.html" %}
{% block title %}
<title>Delete Multiple</title>
{% endblock %}
{% block content %}
<h1>Delete Multiple Items</h1>
<br>
<form class="ManualForm" action ="." method="POST"> {% csrf_token %}
{{ form.management_form }}
<table border="2">
<tr><th colspan="3" scope="row">Select Items to Delete</th></tr>
{% for item_form in form %}
<tr>
<td><label for="{{ item_form.asset.id_for_label }}">AssetTag {{forloop.counter}}:</label>
{% if item_form.non_field_errors %}
{{ item_form.non_field_errors }}
{% endif %}
{% if item_form.asset.errors %}
{{item_form.asset.errors}}
{% endif %}
</td>
<td>{{item_form.asset}}</td>
<td>{{item_form.delete}}
{% if item_form.delete.errors %}
{{item_form.delete.errors}}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<br>
<input class = "btn btn-success" type="submit" value="Delete Selected" />
Cancel
</form>
<form class="AutoForm" action ="." method="POST"> {% csrf_token %}
{{form.as_table}}
<input class = "btn btn-success" type="submit" value="Delete Selected" />
Cancel
</form>
{% endblock %}
When I submit AutoForm, everything is great. It takes me to app_name:url_name, but if I sumbit ManualForm I don't get redirected. It will simply clear all data and reload the form page with empty fields.
The HTTP POST response status code for AutoForm is 302, while for ManualForm is 200.
I don't understand how the template could influence the behavior of the url redirection. What am I doing wrong in the manual rendering of the formset?
It seems that adding:
{% for field in item_form.hidden_fields %}
{{field}}
{% endfor %}
under {% for item_form in form %} will solve the issue.
I didn't understand very well from the docs:
Looping over hidden and visible fields
If you’re manually laying out a form in a template, as opposed to
relying on Django’s default form layout, you might want to treat
< input type="hidden"> fields differently from non-hidden fields. For
example, because hidden fields don’t display anything, putting error
messages “next to” the field could cause confusion for your users – so
errors for those fields should be handled differently.
I just thought this is about errors, so I didn't care. But one of the first thing it says about forms is this:
As an example, the login form for the Django admin contains several
< input> elements: one of type="text" for the username, one of
type="password" for the password, and one of type="submit" for the
“Log in” button. It also contains some hidden text fields that the
user doesn’t see, which Django uses to determine what to do next.
It also tells the browser that the form data should be sent to the URL
specified in the < form>’s action attribute - /admin/ - and that it
should be sent using the HTTP mechanism specified by the method
attribute - post.
Maybe it will help someone else.
This is my first time using Django and I am very simply trying to save text to the database. I have created the table inputs in the database.
I am getting the following error;
Error - Page not found (404)
My code is as follows;
Models.py
from django.db import models
class Input(models.Model):
waist = models.IntegerField(default=0)
height = models.IntegerField(default=0)
def __unicode__(self):
return "{0} {1} {2}".format(
self, self.waist, self.height)
forms.py
class InputForm(forms.ModelForm):
class Meta:
model = Input
fields ={
'waist',
'height'
}
views.py
def InputView(request):
if request.POST:
form = InputForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('account/input')
else:
form = InputForm()
args = {'form' : form}
return render(request,'accounts/input.html', args)
urls.py
url(r'^input/$',views.InputView, name='view_input')
input.html
{% extends 'base.html' %}
{% block head %}
<title> Edit Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<h1> Enter Body Details </h1>
<br>
<br>
<form action="account/input" method="post">
{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="Submit" name="submit" value="submit"/>
</form>
</div>
{% endblock %}
If any one can help it would be greatly appreciated.
HttpResponseRedirect('account/input')
you need to add one more '/' to the beginning like
HttpResponseRedirect('/account/input')
Another way to do it is to use reverse() so if you change the URL you don't have to change your code and you avoid mistakes entering the URL.
Instead of
HttpResponseRedirect('/account/input')
use
HttpResponseRedirect(reverse('view_input'))
remember to add the import
from django.urls import reverse
I want to save and filter users objects in my django app. After inputting the below codes, the imagefield keeps giving me a validation error, saying:
This field is required.
It’s pointing to the imagefield that I should fill it. How can I get rid of that error and make it filter?
Models
class Fin(models.Model):
user=models.ForeignKey(User)
title=models.CharField(max_length=250)
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
address=models.CharField(max_length=200)
city=models.CharField(max_length=200)
state=models.CharField(max_length=200)
guideline=models.TextField(max_length=1000)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return self.title
class FinForm(ModelForm):
class Meta:
model=Fin
fields=('title','main_view','side_view', 'address','city','state','guideline')
exclude=('user')
Views
def fincrib(request):
extra_data_context={}
#if there's nothing in the field do nothing.
if request. method=="POST":
form =FinForm(request.POST)
if form.is_valid():
data=form.cleaned_data
newfincribs=Fin(
user= request.user,
title=data['title'],
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
address=data['address'],
city=data['city'],
state=data['state'],
guideline=data['guideline'])
newfincribs.save()
extra_data_context.update({'FinForm':form})
else:
form = FinForm()
extra_data_context.update({'FinForm':form})
extra_data_context.update({'Fins':Fin.objects.filter(user=request.user)})
plan=Fin.objects.filter(user=request.user)
paginator=Paginator(plan, 5)
try:
page=request.GET.get('page', '1')
except ValueError:
page=1
try:
Fins=paginator.page(page)
except (EmptyPage, InvalidPage):
Fins=paginator.page(paginator.num_pages)
extra_data_context.update({'Fins': Fins})
return render_to_response('post.html',extra_data_context,context_instance=RequestContext(request))
Template
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<center> {{FinForm.as_p}} </center>
<input type="submit" value="Submit"/>
</form>
{% for Fin in Fins.object_list %}
<tr>
{{Fin.user}} </p> </strong>
<p>{{Fin.title}}</p>
<p><img src="{{MEDIA_URL}}/{{Fin.main_view}}"/></p>
<p> <img src="{{MEDIA_URL}}/{{Fin.side_view}}"/></p>
<p> {{Fin.address}} </p>
<p> {{Fin.city}}</p>
<p> {{Fin.state}}</p>
<p> {{Fin.guideline}}</p>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if Fins.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ Fins.number }} of {{ Fins.paginator.num_pages }}
</span>
{% if Fins.has_next %}
next
{% endif %}
</span>
</div>
{% endblock %}
It's because by default all model fields are required, it means if you want to create and save new model instance in the database, you should fill all the mandatory fields. Maybe
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
is giving you the error, because there is no data.
change
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
to
main_view=models.ImageField(upload_to="photos", blank=True, null=True)
side_view=models.ImageField(upload_to="photos", blank=True, null=True)
btw, im not sure which django version you're using but your code is rather messy, any reason you're not using CBVs and static tags?