I am trying to make a simple form in Django that accepts some file upload fields and a few float fields. However, when I run this in my browser, the is_valid() never gets triggered even when all forms are filled in. I have looked through the Django docs and have tried to recreate the examples as much as possible, but I can't figure out what is wrong. I know that the is_valid() is not true because the page does not redirect to another page when submit is pressed. Also, if I go into the admin page, no instances of MyModel are made.
Here is my code.
models.py:
from django.db import models
# Create your models here.
class MyModel(models.Model):
file1 = models.FileField()
file2 = models.FileField()
x = models.FloatField()
y = models.FloatField()
z = models.FloatField()
def __str__(self):
return self.file1
forms.py:
from django import forms
from django.forms import ModelForm
from .models import MyModel
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import MyForm
# Create your views here.
def index_view(request):
if request.method == 'POST':
form = MyForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('some_page')
else:
form = DocumentsForm()
return render(request, 'index.html', {'form':form})
index.html:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Home Page!</h1>
<form method="POST" action="/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Submit">
</form>
</body>
</html>
My guess is it has to do with the fact that you haven't included enctype="multipart/form-data" in your <form> declaration in the HTML. It should look like this:
<form action="/" method="post" enctype="multipart/form-data" class="">
The multipart/form-data is necessary when uploading a file through forms.
Since you are sending both data and files, you need to specify the encoding of the form to:
<form enctype="multipart/form-data" method="POST" action="/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Submit">
</form>
Related
I have a quiz. I have 2 pages, I create the questions and their answers on the first page and I put these questions on the second page, but I want these questions to have the Answer model input, i.e. each question has its own input. When I try to set a query with an Id in the view and the unsuitable Answer form to save does not work, it is not stored in the database. How do I save?
models.py
from django.db import models
# Create your models here.
class Question(models.Model):
question=models.CharField(max_length=100)
answer_question=models.CharField(max_length=100, default=None)
def __str__(self):
return self.question
class Answer(models.Model):
questin=models.ForeignKey(Question, on_delete=models.CASCADE, related_name="questions")
answer=models.CharField(max_length=100,blank=True)
def __str__(self):
return str(self.questin)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from .models import Question,Answer
class QuestionForm(forms.ModelForm):
class Meta:
model=Question
fields="__all__"
class AnswerForm(forms.ModelForm):
class Meta:
model=Answer
fields="__all__"
views.py
from django.shortcuts import render
from django.shortcuts import render, HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from .forms import QuestionForm,AnswerForm
from .models import Question
import random
def home(request):
form=QuestionForm
if request.method=='POST':
form=QuestionForm(request.POST)
if form.is_valid():
form.save()
return render(request, "question/base.html", {"form":form})
def ans(request):
form=AnswerForm
questions=Question.objects.all()
if request.method=="POST":
instance=Question.objects.get(id=request.POST['i_id'])
print(instance)
form=AnswerForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return render(request, "question/ans.html", {"form":form, "questions":questions})
ans.html
<!DOCTYPE html>
<html>
<head>
<title>question</title>
</head>
<body>
{% for i in questions %}
<form method="POST" novalidate>
{% csrf_token %}
<input type="hidden" name="i_id" value="{{ i.id }}" />
{{i}}
{% for a in form %}
{{a}}
{% endfor %}
<input type="submit" name="sub">
</form>
{% endfor %}
</body>
</html>
Try to different approaches to create the pages in html and c
So, I've been trying hard, getting values from input fields in my custom form.
I have a url that corresponds to the form and that form redirects it to the same form again.
The view of the form url checks whether the request method is Post. If it is, then I declare a variable equal to request.POST, I then assigned those values to my model- item_description(). Here is the code of the views.py:
def addItem(request):
if request.method == "POST":
data = request.POST
print(data.__dict__)
item_description(item_name=data.item_name, item_number=data.item_number, item_quantity=data.item_quantity)
else:
HttpResponse("Something went wrong!")
return render(request, 'ims/addItemForm.html')
HTML form:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>IMS| Add Item</title>
</head>
<body>
<form action="{% url 'Item-addition' %}" method="post">
{% csrf_token %}
<input type="text" name="item_name" placeholder="Enter Item Name">
<input type="text" name="item_number" placeholder="Enter Item Number">
<input type="text" name="item_quantity" placeholder="Enter Item Quantity">
<button type="submit" name="add" value="add">Add Item</button>
</form>
See items
</body>
</html>
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('add_item', views.addItem, name='Item-addition'),
path('items', views.itemsList, name='Items-list'),
]
models.py:
from django.db import models
class item_description(models.Model):
item_name = models.CharField(max_length=200)
item_number = models.CharField(max_length=200)
item_quantity = models.CharField(max_length=200)
def __str__(self):
return self.item_name
Also, I printed out the request which is a dictionary, but it was not having any of the values. Here is the printed request dictionary: {'_encoding': 'utf-8', '_mutable': False}.
Here is the error which I am getting:
File "/home/zaid/inventoryManagement/venv/src/ims/views.py", line 13, in addItem
item_description(item_name=data.item_name, item_number=data.item_number, item_quantity=data.item_quantity)
AttributeError: 'QueryDict' object has no attribute 'item_name'
Please help me getting values from the input fields.
Your mistakes:
item_description(item_name=data.item_name, item_number=data.item_number, item_quantity=data.item_quantity)
data is a QueryDict, so you must access the data in it using data['item_name'] or data.get('item_name') as you would for a regular dict.
item_description(...) doesn't actually do anything. It does not save anything to the database. To save to the database, you must use item_description.objects.create(...).
Other problems with your code:
you render the form fields on your own
you extract the POST data on your own
you attempt to save to the database on your own
you are missing input validation (what if some required values are missing? e.g. what if item_name is not submitted?)
you did not provide a suitable error message as feedback to the user if he/she enters inappropriate values (e.g. a string of length 201).
Django's ModelForm is able to handle all of these issues, so please use ModelForm instead.
If models.py is this:
from django.db import models
class ItemDescription(models.Model):
item_name = models.CharField(max_length=200)
item_number = models.CharField(max_length=200)
item_quantity = models.CharField(max_length=200)
def __str__(self):
return self.item_name
Then, create a ModelForm in forms.py:
from django import forms
from .models import ItemDescription
class ItemDescriptioneForm(forms.ModelForm):
class Meta:
model = ItemDescription
fields = ['item_name', 'item_number', 'item_quantity']
In your views.py, use the ModelForm you just created:
from django.shortcuts import render, redirect
from .forms import ItemDescriptionForm
def addItem(request):
if request.method == 'POST':
form = ItemDescriptionForm(request.POST)
if form.is_valid():
form.save()
return redirect('Items-list')
else:
form = ItemDescriptionForm()
return render(request, 'ims/addItemForm.html', {
'form': form,
})
Show the form in your template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Item</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
</body>
</html>
I want to upload multi img to 1 post on Django. I used ImageField in models.py. But it's just can upload 1 image to 1 post. How can i upload multi image to 1 post with Django or someways to solved that problem. Thank you so much.
Sorry for the past answer.
I think this is the best way.
models.py
from django.db import models
from django.template.defaultfilters import slugify
class Post(models.Model):
title = models.CharField(max_length=128)
body = models.CharField(max_length=400)
def get_image_filename(instance, filename):
title = instance.post.title
slug = slugify(title)
return "post_images/%s-%s" % (slug, filename)
class Files(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
files = models.FileField(upload_to=get_image_filename, verbose_name='File')
I did not create a form for the files because we will write it manually in the template.
forms.py
from django import forms
from .models import Post, Images
class PostForm(forms.ModelForm):
title = forms.CharField(max_length=128)
body = forms.CharField(max_length=245, label="Item Description.")
class Meta:
model = Post
fields = ('title', 'body', )
views.py
from django.shortcuts import render
from django.contrib import messages
from django.http import HttpResponseRedirect
from .forms import PostForm
from .models import Post, Files
def post(request):
if request.method == 'POST':
print(request.FILES.getlist('files'))
postForm = PostForm(request.POST)
if postForm.is_valid():
post_form = postForm.save(commit=False)
post_form.save()
if request.FILES.getlist('files'):
for file in request.FILES.getlist('files'):
obj = Files(post=post_form, files=file)
obj.save()
messages.success(request, "Yeeew, check it out on the home page!")
return HttpResponseRedirect("/")
else:
print(postForm.errors)
else:
postForm = PostForm()
return render(request, 'index.html', {'postForm' : postForm})
index.html
<html>
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in postForm.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in postForm %}
{{ field }} <br />
{% endfor %}
<input type="file" id="files" name="files" multiple><br>
<input type="submit" name="submit" value="Submit" />
</form>
</html>
We make such a field for the model of files that we do not form.
<input type="file" id="files" name="files" multiple><br>
You can select multiple files and upload them by holding down CTRL or Shift.
i think you are asking inline models,
https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#inlinemodeladmin-objects
models.py:
from django.db import models
from django.contrib.auth.models import User
class Electronics(models.Model):
ELEC_CHOICES = (
('LAP', 'Laptops'),
('MOB', 'Mobiles'),
('WAT', 'Watches'),
('CAM', 'Camera'),
)
elec_name = models.CharField(max_length=3, choices=ELEC_CHOICES)
elec_image = models.ImageField('Label', upload_to='C:/Users/User/Desktop/')
elec_price = models.IntegerField('Price')
elec_stock = models.BooleanField(default=False)
forms.py:
from django import forms
from django.forms import ModelForm
from .models import Electronics
class ElectronicsForm(ModelForm):
class Meta:
model = Electronics
fields = '__all__'
views.py:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .models import Electronics
from .forms import ElectronicsForm
# Create your views here.
def eleclist(request):
elec = Electronics.objects.order_by('elec_name')
return render(request, 'index.html', {'elec': elec})
def elecadd(request):
if request.method == 'POST':
form = ElectronicsForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('shopp:eleclist'))
else:
print(form.errors)
else:
form = ElectronicsForm()
return render(request, 'add.html', {'form': form})
my add.html:
<html>
<head><title>Electronics</title></head>
<body>
<form method = "post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit" value="create">
</form>
</body>
</html>
I'am first time trying to upload an image using django model forms. But when I clicked submit, the image didn't get saved. It raises error 'this field is required'.
I've looked in some django docs also, but it has very concise material.
You need to add enctype="multipart/form-data" to your form tag, otherwise your file won't be uploaded to server. So update your form template to:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value="create">
</form>
I am very new to Django forms. I am trying to simply get a value from a text field and store it in a database. I am getting an error report saying:
*Forbidden (403)
CSRF verification failed.
Request aborted.
Reason given for failure:
CSRF token missing or incorrect.
For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.*
Where am I going wrong?
My views.py code is:
from django.shortcuts import render
from feedback.models import Test
from mysite.forms import TestForm
from django.http import HttpResponse
from django.template import Context, loader
def test_view(request):
form = TestForm
t = loader.get_template('form.html')
c = RequestContext(request,{'n':''})
if request.method=='POST':
form = TestForm(request.POST)
if form.is_valid():
in_name = request.POST.get("firstname")
fd = Test(name = in_name)
fd.save()
return HttpResponse(t.render(c))
My models.py code is:
from django.db import models
from django.forms import ModelForm
class Test(models.Model):
name = models.CharField(max_length=255)
class TestForm(ModelForm):
class Meta:
model = Test
fields = ['name']
My forms.py code is:
from django import forms
class TestForm(forms.Form):
name = forms.CharField()
My HTML template is:
<!DOCTYPE html>
<html>
<head>
<title>test form</title>
</head>
<body>
<form method = "POST">
{% csrf_token %}
First name:<br>
<input type="text" name="firstname" value = {{ n }}>
<br><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
You do it in a wrong, very PHPish, way.
Move the form definition from models.py to the forms.py, so your feedback/forms.py should be:
from django.forms import ModelForm
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ['name']
The feedback/views.py should be simplified to:
from django.shortcuts import render, redirect
from feedback.forms import TestForm
def test_view(request):
if request.method == 'POST':
form = TestForm(request.POST)
if form.is_valid():
form.save()
return redirect('.')
else:
form = TestForm()
return render(request, 'form.html', {'form': form})
And the template:
<!DOCTYPE html>
<html>
<head>
<title>test form</title>
</head>
<body>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
</body>
</html>