Uploading text files in Django - python

I have a form.py including Floatfield and Charfield. Now I want to add a new Filefield to upload a text file. But I fail.
The float var is submitted successfully and I could see they are changed with the change of the input, but I cannot find the file in located folders.
And also, how could I check whether file extensions are correct? Should I achieve it in view or model?
Could someone help me? I truly struggled with it.
model.py
file = models.FileField(upload_to='/Folder', null = True)
form.py
file = forms.FileField(label='data', required=False)
view.py is followed the structure in Django official document.
def handle_uploaded_file(f):
with open('./test_temp_file.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
def file_upload(request):
if request.method=='POST':
form = input_form(request.POST,request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
name = request.FILES['filename'].name
time = cleaned_data(timezone.now())
form = {
'name' : name,
'time' : time
}
return render(request, 'home/results.html',{'form':form})
else:
form = input_form()
return render(request, 'home/input.html', {'form': form})
------Uploaded:
HTML page is like this:
<form method = "POST" enctype="multipart/form-data" name="temp_data_upload">
{% csrf_token %}
{{ form_upload.temp_data.errors }}
{{ form_upload.temp_data }}
{% endif%}
</form>

You should save your form and refactor the code.
def file_upload(request):
if request.method=='POST':
form = input_form(request.POST,request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
name = request.FILES['filename'].name
time = cleaned_data(timezone.now())
form = {
'name' : name,
'time' : time
}
form.save() # <-- save your form
return render(request, 'home/results.html',{'form':form})
else:
form = input_form()
return render(request, 'home/input.html', {'form': form})
EDIT
Make sure your forms contain the correct values.
<form method="POST" enctype="multipart/form-data">

Related

How to show many-to-many fields from form on on HTML form in Django

I couldn't get my input data to many-to-many field data via the HTML form. How to solve this?
This is my code:
models.py
class SetStaffSchedule(models.Model): # generated work for staffs by admins
schedule = models.ManyToManyField('Staff')
shift = models.DateTimeField("Shift")
detail = models.TextField("Task Detail", max_length=200)
def __str__(self):
return self.shift
def __str__(self):
return self.detail
forms.py
from django import forms
from attendance.models import SetStaffSchedule, Staff
class SetStaffScheduleForm(forms.ModelForm):
class Meta:
model = SetStaffSchedule
fields = ['schedule','shift', 'detail']
views.py
def schedules(request): # getting schedules for staffs' work
all_schedules = SetStaffSchedule.objects.all()
context = {
'all_schedules': all_schedules
}
return render(request, 'getschedule.html', context)
def post(request): # posting schedules for staffs' work
form = SetStaffScheduleForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save();
return redirect ('schedules')
return render(request, 'post_schedules.html', {"form": form})
post_schedules.html
{% csrf_token %}
{{ form.as_p }}
You need to handle the case where the request method is "GET" so that you can render the form without any validation being run. If the user then submits the form as a "POST" you should run the validation/saving
def create_staff_schedule(request): # posting schedules for staffs' work
if request.method == 'GET':
form = SetStaffScheduleForm()
else: #  POST
form = SetStaffScheduleForm(request.POST)
if form.is_valid():
form.save()
return redirect('schedules')
return render(request, 'post_schedules.html', {"form": form})
You need to also wrap the form in a form tag with the method set to "post"
<form method="post">
{% csrf_token %}
{{ form.as_p }}
</form>

Passing Dropdown Value To URL in Django

I am rendering a dropdown which displays a list of integers. This is the only field in the form/view. Once that form is submitted, the integer selected should be passed to the URL of the next view which is rendered on submission of the previous form.
I am getting a 404 when I attempt this.
Here is what I am currently trying:
forms.py
#this is the dropdown field
class ManifestDropDown(forms.Form):
reference = forms.ModelChoiceField(queryset=Orders.objects.values_list('reference', flat=True).distinct(),
empty_label=None)
views.py
#this is the view where the dropdown is submitted
def manifest_references(request):
if request.method == 'POST':
form = ManifestDropDown(request.POST)
if form.is_valid():
reference_id = form.cleaned_data.get('reference')
form.save()
return render('manifest', reference_id=reference_id)
query_results = Orders.objects.all()
reference_list = ManifestDropDown()
context = {
'query_results': query_results,
'reference_list': reference_list,
}
return render(request, 'manifest_references.html', context)
#this is the view where the value should be displayed in the url
def manifest(request, reference_id):
form = CreateManifestForm(request.POST)
if request.method == "POST":
....
data = Manifests.objects.all().filter(reference__reference=reference_id)
form = CreateManifestForm(initial={
'reference': Orders.objects.get(reference=reference_id),
})
total_cases = Manifests.objects.filter(reference__reference=reference_id).aggregate(Sum('cases'))
context = {
'reference_id': reference_id,
'form': form,
'data': data,
'total_cases': total_cases['cases__sum'],
}
return render(request, 'manifest_readonly.html', context)
urls.py
#url which displays the manifest view above
url(r'^manifest/(?P<reference_id>\d+)/$', manifest, name='manifest'),
url(r'^references_manifests', manifest_references, name='references_manifests'),
manifest_references.html
<div class="container">
<br>
<br>
<br>
<form method="POST" action="references_manifests">
{% csrf_token %}
{{ reference_list }}
<button type="submit" class="btn btn-primary" name="button">Create Proforma</button>
</form>
</div>
To dynamically change the URL that you're actually submitting to, you would need to use JavaScript.
But an alternative is to submit back to the manifest_references view, then redirect from there to manifest. (Note, you should always be redirecting, not rendering, after a successful submission anyway. And no need to call form.save(), this isn't a modelform so there is nothing to save.)
def manifest_references(request):
if request.method == 'POST':
form = ManifestDropDown(request.POST)
if form.is_valid():
reference_id = form.cleaned_data.get('reference')
return redirect('manifest', reference_id=reference_id)
You can do two things:
Call the manifest view directly.
Redirect the user to the manifest page.
The first one should be done like this:
if form.is_valid():
reference_id = form.cleaned_data.get('reference')
form.save()
return manifest(request, reference_id)
The second one can be done like this:
if form.is_valid():
reference_id = form.cleaned_data.get('reference')
form.save()
return HttpResponseRedirect(reverse('manifest', reference_id = reference_id))
It doesn't really matter which one you do, although I would recomment redirecting the user to the correct page, because then a refresh will not resend the form the user has entered.

How to display an Excel sheet in Django?

im working on a Django website and i wnat to display an Excel Sheet that can later be edited on the website. Right now i am only able to upload a file but nothing is displayed. I know FileField is probably the way to go but how do i make the file show on the webpage? Django-excel seems does not do the job for me, because i think there is a much easier way to just display a file (but not an image).
Here is my models.py
from django.db import models
class Document(models.Model):
description = models.CharField(max_length=255, blank=True)
document = models.FileField(upload_to="documents/")
uploaded_at = models.DateTimeField(auto_now_add=True)
Here is my views.py
class UploadFileForm(forms.Form):
file = forms.FileField()
def index(request):
documents = Document
template = loader.get_template('documents/index.html')
context = {
'documents' : documents
}
return HttpResponse(template.render(context, request))
def model_form_upload(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('documents:index')
else:
form = DocumentForm()
return render(request, 'documents/model_form_upload.html', {
'form': form
})
My forms.py
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('description', 'document')
and my upload_template.html where the file should be displayed at the end
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
<p>Return to Home</p>
I think i'll just have to change something in the views.py but i ran out of ideas. Any answers would be appreciated.

Textarea not shown in Django form

I'm new to Django
In my homepage, I want to give 2 choices to users: to upload photos to a new album, or to an existing one.
The problem is one of the forms is initially not shown in the HTML,I can only see its submit button. But when I click on the submit button, then the form appears, along with the 'This field is required' warnings.
For this I have created 2 forms in forms.py
class AlbumForm(ModelForm):
class Meta:
model = Album
fields = ('title', 'description',)
class dropDownForm(forms.Form):
Albums = forms.ModelChoiceField(queryset=Album.objects.filter(user__id=1))
def __init__(self, user, *args, **kwargs):
super(dropDownForm, self).__init__(*args, **kwargs)
self.fields['Albums'].queryset = Album.objects.filter(user__id=user.id)
AlbumForm is for creating a new album, dropDownForm is for choosing from an existing one.
In views.py I have:
def upload_album(request):
if request.user.is_authenticated():
if request.user.albums.all() is not None:
albums = request.user.albums.all()
dropdownAlbum = request.POST.get('Albums')
if request.method == 'GET':
album = AlbumForm()
form = dropDownForm(request.user)
if ((request.method == 'POST') and ('ExistingAlbum' in request.POST)):
form = dropDownForm(request.user)
userID = request.user.id
curr = UserProfile.objects.filter(id=userID).first()
curr.currentAlbum = int(dropdownAlbum)
intAlbum = int(dropdownAlbum)
curr.save()
return HttpResponseRedirect('/upload-media')
if ((request.method == 'POST') and ('CreateNewAlbum' in request.POST)):
form2 = AlbumForm(request.POST)
if form2.is_valid():
album = form2.save(commit=False)
album.user = request.user
album = form2.save()
created_album_id = Album.objects.filter(title=album).first().id
userID = request.user.id
curr = UserProfile.objects.filter(id=userID).first()
curr.currentAlbum = created_album_id
curr.save()
request.user.albums.add(album)
return HttpResponseRedirect('/upload-media/')
return render(request, "base.html", locals())
and in HTML:
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="ExistingAlbum" value="Continue" href="/upload-media/">
</form>
</div>
<div>
<form method="POST">
{% csrf_token %}
{{ form2.as_p }}
<button type="submit" name="CreateNewAlbum" value="Create New Album">Create</button>
</form>
</div>
Any help is appreciated.
I've just looked up what locals actually is and that is a horrible way of constructing your context data (which is why I'm not surprised I haven't ever heard of it).
Your context data should be a dictionary made up of those values that you need in order for your template to render correctly. Therefore you should construct a dictionary that includes the elements that you need.
As a starting point that would be.
{
'form': AlbumForm(),
'form2': dropDownForm(request.user)
}
My guess is form2 does not appear.
The problem is: when you initially request the page it's a GET request, therefore only the following part is executed:
if request.method == 'GET':
album = AlbumForm()
form = dropDownForm(request.user)
return render(request, "base.html", locals())
Because other if branches require POST, which is a request verb used when submitting the data, which occurs when you press the Submit button.
When you call locals() the context is filled with album and form, but not form2, because it's not initialized in local scope in this case. You need to add form2 initialization to the above part, e.g.:
if request.method == 'GET':
form2 = AlbumForm()
form = dropDownForm(request.user)
...
return render(request, "base.html", locals())
P.S. Using locals() to fill a context is smart, but bad idea - it's insecure, it adds ALL the variables defined in the local scope to the context available in template.

Django import csv HTML

hi im currently try to import a csv file into a django project with out using the django admin. the code ive written seems to work when in python run but im unsure about how to build the html template as i cant seem to find any examples. Is anyone able to either post an example or point me in the right direction
my code is
Forms
class DataInput(forms.Form):
file = forms.FileField()
def save(self):
records = csv.reader(self.cleaned_data["file"])
for line in records:
parts = Part()
parts.supplier_id = line[0]
parts.name = line[1]
parts.description = line[2]
parts.save()
view
def csv_import(request):
if request.method == "POST":
form = DataInput(request.POST, request.FILES)
if form.is_valid():
form.save()
success = True
context = {"form": form, "success": success}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
else:
form = DataInput()
context = {"form": form}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
thanks in advance
Your upload template will look something like this if you just want to use the default form rendering:
<!DOCTYPE html>
<html>
...
<form enctype="multipart/form-data" method="post" action=".">
{{ form }}
</form>
...
</html>
The distinguishing part is the enctype="multipart/form-data" that lets it handle the file upload field.

Categories