I'm trying to submit a form containing a file without django model form.
Can I still use upload_to?
How does it work?
example:
models.py
blabla = models.FileField(upload_to='')
views.py
form = BlaForm(request.POST or None, request.FILES or None)
templates.html
<form method="post" class="form-horizontal" action='' enctype="multipart/form-data">
Related
Currently I am starting to develop a django project which need to provide a HTML page for other students to upload their experiment results which are excel files (maybe CSV), and save them to databases. But I don't know what should I do with the model.py file for each student have diffenent assignments which means the first row of different experiments are not the same. Can anyone help me?
Django 2.1.7
try this
in template
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
in forms.py
from django import forms
from .models import YourModel
class YourModelForm(forms.ModelForm):
class Meta:
model = YourModel
fields = ('myfile', )
in views.py
def file_upload(request):
if request.method == 'POST':
form = YourModelForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
form = DocumentForm()
return render(request, 'template', {
'form': form
})
for more details refer this
hope it helps
I'm collecting data from form, processing data(right now I'm not) and displaying the result on the same HTML page from where the user submits the form.
Here is my views.py file:
def index(request):
template = 'predictor/index.html'
if request.method =='POST':
form = EvalForm(request.POST)
if form.is_valid():
text ='thank you for submitting form'
else:
text='something wrong.'
context: {
'text':text,
}
return render(request,template,context)
else:
form = EvalForm()
return render(request,template)
Here is my index.html file
<form method="POST" action="{% url 'predictor' %}">
{% csrf_token %}
//all input fields including submit button here
</form>
<div class="result">
{{ text }}
</div>
All other things like urls are configured properly.
What I'm doing wrong here?
You have typo in your code.
Should be context = {'text':text,} instead of context: {'text':text,}.
I have a template which displays a certain ModelForm at one of the URLs of my Django site. The ModelForm is based on a model with two fields,
class ActionCode(models.Model):
action_code = models.CharField(blank=False, max_length=10,
verbose_name="Action Code")
description = models.TextField(blank=True)
class Meta:
unique_together = ('action_code',)
I would like my ModelForm to give the user only the first field (Action Code), then when it is submitted, verify if the value entered already exists or not. If it doesn't already exist, I want to redirect the user to be able to enter a Description for that Action Code (the second field in my model). So I wrote a second ModelForm which uses the Description field of the model, and I would like my first form to redirect to the second form after validating that the data is new. Ideally then, the Description would be linked to this specific piece of data and both would go into the same Django database table (hence them coming from the same model). However, when I enter a new piece of data and hit Submit, the site simply stays at the /action_code/ URL and displays a Submit button, and nothing else. How do I get the first form to redirect to the second form, and what is the best way to make sure it only does so if the data is new?
Here are my urls.py:
url(r'^action_code/', action_code_form, name="actioncode"),
url(r'descr_form/', code_description_form, name='description'),
Here are my two forms in `forms.py':
class ActionCodeForm(ModelForm):
class Meta:
model = ActionCode
fields = ('action_code',)
class ActionCodeDescriptionForm(ModelForm):
class Meta:
model = ActionCode
fields = ('description',)
Here is my views.py:
def action_code_form(request):
form = ActionCodeForm()
description_form = ActionCodeDescriptionForm
if request.method == 'POST':
form = ActionCodeForm(request.POST)
if form.is_valid():
action_code = form.cleaned_data['action_code']
form.save()
return render(request, 'description_form.html',
{'form': description_form})
return render(request, 'action_code_form.html', {'form': form})
def code_description_form(request):
form = ActionCodeDescriptionForm()
if request.method == 'POST':
form = ActionCodeDescriptionForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'description_form.html', {'descr_form': form})
And my templates:
action_code_form.html:
<form method="post" action="">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type="submit" value="Submit"/>
</form>
description_form.html:
<form method="post" action="">
{% csrf_token %}
<table>
{{ descr_form }}
</table>
<input type="submit" value="Submit"/>
</form>
Forms don't redirect to anything. It's the view's responsibility to do the redirect.
You need two views, with two URLs; when the first form submission is successful, the view should redirect to the second URL.
I`m using Django 1.9 with the following:
views.py:
def a_new(request):
# submit button
if request.method == "POST":
form = AForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('ui:config-list')
# first visit
else:
form = AForm()
template = 'api/test_template.html'
context = RequestContext(request, {'form': form})
return render_to_response(template, context)
forms.py:
class AForm(forms.ModelForm):
b= forms.ModelMultipleChoiceField(
queryset=B.objects.all(),
widget=FilteredSelectMultiple("b", is_stacked=False)
)
class Meta:
model = A
fields = ('name', 'b', )
test_template.html
...
<form role="form" class="form-inline" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form.name }}
{{ form.b }}
</div>
<div class="dl-horizontal">
<button type="submit" class="btn btn-success">Save</button>
</div>
</form>
models.py:
class A(models.Model):
name = models.CharField(max_length=100)
b = models.ManyToManyField(B, null=True, blank=True, name='b')
...
The problem is that when I use the Save button - only the name field is created in the item. The b item, that the widget is being used on, is just not being saved to the DB with the new item A created(it does show error if I leave the b field empty so I guess its checking it too).
What can be the problem?
See the documentation about using commit=False when you have a many-to-many field.
Note that there is no reason for you to be using commit=False here though. Remove it, and the second save, and Django will save your values directly.
b is ManyToManyField, it does on saved on the table A. In a different table the relation between A and B is maintained.
If you have an M2M field and do save(commit=False) you need to call this at the end:
form.save_m2m()
See the docs.
I have the below model;
class AudioFile(models.Model):
name = models.CharField(max_length=100, default='')
audio_file = models.FileField()
uploader = models.ForeignKey(User, default='')
def __unicode__(self):
return self.name
The below form;
class AudioFileForm(forms.ModelForm):
class Meta:
model = AudioFile
fields = ['name', 'audio_file']
def clean_audio_file(self):
audio = self.cleaned_data.get('audio_file',False)
if audio:
if audio._size > 5*1024*1024:
raise ValidationError("File too large ( > 5mb )")
if os.path.splitext(audio.name)[1] != ".mp3":
raise ValidationError("We only support mp3!")
return audio
else:
raise validationError("Couldn't read uploaded file")
As you can see there's some custom validations
Then I have the below html with the AudioFileForm passed as form;
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="post" action="{% url 'actual_upload_audio' %}">
{% csrf_token %}
{{ form }}
<input type="submit" value="Upload"/>
</form>
</body>
</html>
Now I know how to save the object had it not been containing a FileField. I would do something like this;
form = AudioFileForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
//Say it contained another field, foo
foo = form.cleaned_data['foo']
uploader = request.user //view requires login
audio_file = Audio_File.objects.create(name=name,
foo=foo,
uploader=uploader)
audio_file.save()
return HttpResponse("Success!")
But there being a FileField in question I donno how to handle this. I read Django's documentation but don't really get it. A much easier elaborate explanation would be lovely.
For a start I have MEDIA_ROOT = '/home/afzalsh/works/openradio/audio_files/' in my settings.py
Update
Thanks to #Rohan I now have <form method="post" action="{% url 'actual_upload_audio' %}" enctype="multipart/form-data"> instead of <form method="post" action="{% url 'actual_upload_audio' %}">
Also have the below view thanks to #dzejdzej;
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['uploader'] = request.user
form.save()
return HttpResponseRedirect(reverse('home_audio',kwargs={'pk':audio_file.pk}))
else:
return HttpResponse("Form Invalid!")
But Form Invalid! :/
Your form should have enctype="multipart/form-data" attribute so that it submits files.
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
Since you're using ModelForm, why not let Django handle saving the whole model?
from django.shortcuts import redirect
form = AudioFileForm(request.POST)
if form.is_valid():
form.cleaned_data['uploader'] = request.user //view requires login
form.save()
return redirect(success_url)
If you're using Django >=1.7, upload_to field is no longer required. However, I consider it a good practice.
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.FileField.upload_to
Also redirect user after successful POST to avoid issues with csrf.
you should mention the upload_to attribute as : audio_file = models.FileField(upload_to='uploads')
here 'uploads' is the name of the directory you would like to upload your files to.
As Rohan seaid, you must defile your form in template like this.
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
This allows you to send files with request to view. Now in view you must have something like this:
def my_view(request):
if request.method == 'POST':
my_form = MyForm(request.POST, request.FILES)
if my_form.is_valid():
my_form.save()
You can initial your form FileField and ImageField with request.FILES