I have a Django model containing a fileField and a ModelForm which requests the user upload a file. Yet no matter what I seem to do, the request.FILES returned by the server does not contain anything. Here is the model:
class RepoFile(models.Model):
id = models.IntegerField(primary_key=True)
repo = models.FileField(blank=False, null=True, upload_to="repos/")
The ModelForm:
class RepoUpload(forms.ModelForm):
class Meta:
model = RepoFile
fields = ['repo']
widgets = {
'repo': ClearableFileInput(),
}
And the HTML
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
Also here is the view that I am using:
form = RepoUpload(request.FILES)
if form.is_valid():
print('this passed')
form.save()
I noticed that no matter what file I upload in the "Choose File" section, the form.is_valid() returns false. If I just use HTML and the view to send request.FILES to a manually created object, len(request.FILES) returns 0. Does anyone know of a solution?
you have a wrong init args in form, right is that:
form = RepoUpload(request.POST, request.FILES)
To avoid this error, is better to use:
form = RepoUpload(data=request.POST, files=request.FILES, )
additional kwargs for init:
data=None,
files=None,
auto_id='id_%s',
prefix=None,
initial=None,
error_class=ErrorList,
label_suffix=None,
empty_permitted=False,
field_order=None,
use_required_attribute=None,
renderer=None
Read more here:
https://docs.djangoproject.com/en/4.0/ref/forms/api/#django.forms.Form
Related
I am trying to save a file and some other details in django using forms.
And I only want it to save a CharField and a FileField but not the country field.
For country field I want it to take its value through a post request.
But the form isn't saving. The errors says "data didn't validate".
Also this method works fine if I don't use a FileField.
models.py
class Simple(models.Model):
name = models.CharField(max_length=100)
city = models.FileField(upload_to='marksheet')
country = models.CharField(max_length=100)
forms.py
class SimpForm(forms.ModelForm):
class Meta:
model = Simple
fields = ['name','city']
A snippet from upload.html
<form action="upload" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label>Test input</label>
<input type="text" name="country">
{{form.name}}
{{form.city}}
<button type="submit">Submit</button>
</form>
views.py
def upload(request):
if request.method == 'POST':
a = request.POST.get('country')
form = SimpForm(request.POST,request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.country = a
post.save()
return HttpResponse('saved')
else:
return HttpResponse('ERROR SAVING')
else:
form = SimpForm()
return render(request,'upload.html',{'form':form})
You are not passing request.FILES in your form. You should pass it like this:
form = SimpForm(request.POST, request.FILES)
More information on file uploads can be found in documentation.
I'm trying to get a simple form working. Oddly, other forms I wrote in this app are working fine, but this one wont show the fields. Can anyone tell me what I'm missing? Here are the files
views.py:
def newnote(request, record_id):
if request.method == 'POST':
form = NoteForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/tracker/all/')
else:
form = NoteForm()
return render(request, 'tracker/noteform.html', {'form': form})
models.py
class Note(models.Model):
record = models.ForeignKey(Record, on_delete=models.CASCADE)
note_text = models.CharField('Notes', max_length=2000)
note_date = models.DateField('Date Entered')
forms.py
class NoteForm(forms.Form):
class Meta:
model = Note
fields = ['note_text',
'note_date'
]
template (noteform.html)
<form action="/tracker/newnote/" method="post">
<div id="fields">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</div>
</form>
One other note, I have commented out the div id called "fields", to rule out CSS as the issue.
Your form is based on form.Form, which doesn't know anything about models, doesn't expect a Meta class, and expects all its fields to be declared manually - since you have not declared any fields, nothing will show on the template.
It should inherit forms.ModelForm instead.
I have a form where user just uploads an image,but problem is when I choose an image and press button to submit. It says This field is required.on the page although I have already pointed the image. And that's all it does.I checked if it was actually submitted but no, it was not.What could be the problem ?
Models.py
class pic(models.Model):
username = "anonymous"
picpost = models.ImageField(upload_to='anon_pics')
creation_date = models.DateTimeField(auto_now_add=True)
forms.py
from django import forms
from .models import pic
class PicForm(forms.ModelForm):
class Meta:
model = pic
fields = [
"picpost"
]
view.py
def pic_create(request):
form = PicForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"form" : form,
}
return render(request, "create_pic.html", context)
create_pic.html
<body>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Upload Picture' />
</form>
</body>
Any help is highly appreciated.Thank you very much!
There are two issues here.
Firstly, your view needs to pass request.FILES as well as request.POST to the form.
Secondly, your form element in the template needs to include enctype="multipart/form-data".
I am writing simple blog in django and I gotstuck on uploading files.
I want to create template wher user can write post and add multiple files. So firstrly i have created models:
class Post(models.Model):
title= models.CharField(verbose_name=u"post title", max_length=40, blank=False)
body= models.TextField(verbose_name=u"post body", blank=False)
author= models.ForeignKey(User, blank=False)
published= models.DateTimeField(verbose_name=u"data publikacji", blank=True, null=True)
class Add(models.Model):
post=models.ForeignKey(Post)
file=models.FileField(upload_to='adds', verbose_name=u"added files")
and after that i created template which looks like this:
{% block content %}
<div class="col-lg-6 col-md-offset-3">
<form enctype="multipart/form-data" method="post" adction="{% url 'create_post' %}">{% csrf_token %}
{{post_form|crispy}}
<input type="file" name="files" multiple/></br>
<input class="btn btn-success" style="width:100%" type="submit" value="Dodaj post"/>
</form>
</div>
{% endblock %}
after that i wrote simple view which would handle files and post creation:
def create_post(request):
if request.method== 'GET':
post_form=PostForm()
add_form=AddForm()
context={
'post_form': post_form,
}
return render(request, 'create_post.html', context)
else:
post_form=PostForm(request.POST)
if post_form.is_valid():
instance=post_form.save(commit=False)
instance.published=datetime.datetime.now()
instance.author=request.user
instance.save()
# import ipdb
# ipdb.set_trace()
for file in request.FILES.getlist("files"):
add_instance=AddForm()
add_instance.post=instance
add_instance.file=file
if add_instance.is_valid():
add_instance.save()
return redirect(reverse('AllPosts'))
but none of add_instance passes the validation "is_valid". But why?
And the second question is there any way to use Form in template against writing raw input for file? When i use AddForm i can only add one file what is logic.
You problem is that your form is always an unbounded form, which means that it is initialized without data. By data I mean POST or GET data from request or an instance of the model. unbounded form will always fail is_valid() and it doesn't make sense to manually assign anything to a form instance like add_instance = AddForm() then add_instance.post = instance.
django doc explains how to use a form.
You cannot upload multiple files with one single form because each form is a Add model form. You should really use ModelFormSet for your AddForm to add multiple model instances in one submit.
django doc explains how to use ModelFormSet.
By the way, I find the model name Add extremely confusing, consider changing it to Attachment or PostFile or something else.
Edit:
I didn't try it, but if you want one widget for multiple files, you can do this in views:
for upload_file in request.FILES.getlist('files'):
form = AddForm(request.POST, {'file': upload_file})
if form.is_valid():
new_file = form.save(commit=False)
new_file.post = instance
new_file.save()
I am working on an app that has a section with with a file upload form for .txt fiels. I would like for the current user that is uploading the file to be added along with the file and the file name. Currently, I can do this successfully in the admin section but I just cant get it to save via the form itself. Any Ideas?
Here are the models:
class UploadedTextFile(models.Model):
file = models.FileField(upload_to="textfiles")
filename = models.CharField(max_length = 50)
username = models.ForeignKey(User, blank=True, null=True)
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
Here is my view:
def inputtest(request):
#response for file being submited
if request.method == "POST":
form = UploadedTextFileForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
new_form.username = request.user
new_form.save()
return render(request, 'about.html')
inputtest = UploadedTextFileForm()
return render(request, 'failed.html', {'inputtest': inputtest})
else:
inputtest = UploadedTextFileForm()
return render(request, 'inputtest.html', {'inputtest': inputtest})
Here is my html:
{% extends 'base.html' %}
{% block content %}
<form method="post">{% csrf_token %}
{{ inputtest.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Doing it in the view (as you've shown) is the right way to do this. Most likely you're having problems because you've left username as a field on the form, and because the FK model field doesn't have blank=True set the form requires the field to be provided. You should explicitly declare just the subset fields that you want to accept user input for in the form's Meta class.
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
I am not sure why you're rendering a different template when the form is not valid, but no matter what you're not providing the form object in the context. This means that you'll never see any errors the form detects, which is probably what's happening with this code - you're not seeing the error that username is not provided.