I am creating an app that allows users to convert their .ifc (3D model) files into other data forms (.xlsx, filtered .xlsx, json). I have managed to implement the upload part, but now I am not sure about the download.
I would like to create a "download" button that takes in the users desired download path (maybe even file name). When I have the path I can start my conversion function with the last uploaded file.
def model_form_download(request):
if request.method == 'POST':
download_path = ??? #How to take in the user defined upload path?
last_model = Document.objects.latest("uploaded_at")
last_model_name = last_model.document.name
MODEL_DIR = Path(MEDIA_DIR) / last_model_name
model = parser(MODEL_DIR)
xlsx_name = Path(last_model_name).stem
XLS_DIR = Path(download_path) / (xlsx_name + '.xlsx')
model[1].to_excel(XLS_DIR)
return render(request, 'core/model_form_download.html')
return render(request, 'core/model_form_download.html')
The extra question here is how to take in the user choice of prefered conversion format and use in this view function?
def model_form_download(request):
if request.method == 'POST':
download_path = ??? #How to take in the user defined upload path?
last_model = Document.objects.latest("uploaded_at")
last_model_name = last_model.document.name
MODEL_DIR = Path(MEDIA_DIR) / last_model_name
model = parser(MODEL_DIR)
xlsx_name = Path(last_model_name).stem
XLS_DIR = Path(download_path) / (xlsx_name + '.xlsx')
model[1].to_excel(XLS_DIR)
return render(request, 'core/model_form_download.html')
return render(request, 'core/model_form_download.html')
How to take in the user defined upload path?
if you have a form on the frontend like this:
<form>
<input name="download_path" .../>
...
Then in you django view you can access it from request
download_path = request.POST.get("download_path")
the same goes for the conversion format, just add it to a form and access it from the request object.
although really you should consider using forms: https://docs.djangoproject.com/en/3.2/topics/forms/
Related
I am trying to build a system where users can upload their CSV file in the Django backend. But I am facing a problem, I want to display CSV file only to the user who uploaded it. I make a field in the models which can trace the user who uploaded the file. Here are some of my codes.
CSV file model:
class Data(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,default=1)
filename = models.CharField(max_length=40,blank=False)
csv_file = models.FileField(upload_to='documents/',blank=False)
def __str__(self):
return self.filename
And the view logic:
def accounts(request):
user = Data.objects.values('user')
if user == request.user:
main_data = Data.objects.all()
else:
main_data = ""
dict = {'main_data':main_data, 'name' : request.user.username}
return render(request, 'accounts.html',dict)
I am only getting that else value ' main_data=" " '.
Simply we can do:
try:
data = request.user.data
except Data.DoesNotExist:
data = ''
Also, check the example of one-to-one relationships in Django's Official Documentation.
You are trying to compare the request.user to a queryset and then also returning all Data objects. You need to use the request.user and then return only the objects linked to that user.
def accounts(request):
main_data = Data.objects.filter(user=request.user)
dict = {'main_data': main_data}
return render(request, 'accounts.html', dict)
Also you wont need the 'name' : request.user.username in your dict. You can access the username through the main_data
In my Django "sources" project I have the "bulletins" app.
I have a view "model_form_upload" inside of which I get the uploaded file name ("csvFilename") when I upload it.
views.py
from bulletins.forms import ErnageForm
from bulletins.models import ErnageModel
from bulletins.pretreatment import pretreatment
def model_form_upload(request):
if request.method == 'POST':
form = ErnageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
for filename, file in request.FILES.items():
csvFilename = file.name
resultPretreatment = pretreatment()
print(resultPretreatment)
return redirect('proceed_FT')
else:
return redirect('upload_fail')
else:
form = ErnageForm()
return render(request, 'bulletins/upload_csv.html', {'form': form})
Beside that, I have a python script "pretreatment.py" that effectuates a bunch of pandas-dataframe transformations on my csv file.
pretreatment.py
def pretreatment(csvFileToTreat="..."
#... all the transformations with pandas dataframes...
df.to_csv(txtExportFilePath, index=False, header=None, sep='\t')
models.py
class ErnageModel(models.Model):
csv = models.FileField(upload_to="METEO ERNAGE/{0}/{1}".format(yearToTreat,monthToTreat))
My csvFilename will always be a string of this type : "Ernageyyyymm.csv".
My question here is : How can I collect my csvFilename variable out of the views.model_form_upload function to use its date information it in the pretreatment python script variables "csvFileToTreat" and "txtExportFilePath".
Those two ones are of the type "path/Ernage{0}{1}.format(yearToTreat,monthToTreat).
As I have to use it each month I would like to have my files uploaded in media/METEO ERNAGE/{0}/{1}".format(yearNumber,monthNumber) as you can see in the FileField upload_to and then everything happening in this directory. So the pretreatment charges the uploaded file and then export in it also.
I hope all this is as clear as possible, thank you for your help.
store csvFilename name in a session like this:
request.session['file']=csvFilename
and you can use this session where ever you want like this.
csvFilename =request.session['file']
I have a form with a FileField and other fields:
from flask_wtf.file import FileField
class FooForm(Form):
file = FileField()
#...
How I can "persist" file uploads through multiple request? For example, I attach a file to file upload field and write some text to another field. After I click submit, the text doesn't validate, so I display the form again to review the data, but the file is gone now. How can I improve the form so that the user doesn't have to upload the file again?
The simplest way is to store the file on first load and then reference it by ID after that:
class FooForm(Form):
file = FileField()
file_id = HiddenField()
Then in your handler:
if form.file_id.data:
# remove any validators from form.file
form.file.validators = []
if form.validate():
possible_file_stream = request.files.get(form.file.name)
file_data = get_file(possible_file_stream, form.file_id.data)
# Do things with file data
return redirect('/somewhere/else')
elif form.file.data:
file_data = request.files[form.file.name]
form.file_id.data = save_file(file_data)
# Optionally, if the form should not display the file input
# once one has been uploaded
# del form.file
return render_template("form.html", form=form)
I've set up the Photologue, but I don't know how to let a (normal) user upload an image without using the admin interface.
I'd like to let users upload base64-encoded images from a HTML5 canvas, but in the first step it would be fine to upload files from the user's filesystem.
I guess I could modify this general example on how to upload files to use photologue's photo model. I assume this would mean somehow filling "ImageModel"'s ImageField attribute "image'.
I've actually used the linked file upload guide and adapted it to photologue. From my canvas element I extracted a base64 data url and set a form's field to its value then I could interpret it on Django's server side in a view:
def upload_base64(request):
# Handle file upload
if request.method == 'POST':
form = PhotoCodeForm(request.POST, request.FILES)
if form.is_valid():
uploaded_photo_data = base64.b64decode(request.POST['photocode'])
uploaded_photo_file = ContentFile(uploaded_photo_data)
title_str = "Untitled"
slug = slugify( title_str + str( datetime.now() ) )
uploaded_photo = Photo.objects.create( image = default_storage.save(slug, uploaded_photo_file),
title = slug,
title_slug = slug )
name_upload_gallery = "user-upload-queue"
try:
upload_gallery = Gallery.objects.get(title_slug__exact=name_upload_gallery)
except ObjectDoesNotExist:
return HttpResponseBadRequest('<html><body><p>The gallery "'+name_upload_gallery+'" does not exist.</p></body></html>')
upload_gallery.photos.add(uploaded_photo)
# Redirect to the photo gallery after POST
return HttpResponseRedirect('/canvas/')
else:
return HttpResponseBadRequest('<html><body><p>The entered data was not correct.</p></body></html>')
else:
form = PhotoCodeForm() # A empty, unbound form
return render_to_response(
'photologue_upload/upload_base64.html',
{'form': form},
context_instance=RequestContext(request)
)
upload_base64.html is a very simple form that has a field photocode where the base64 string is pasted to.
I am trying to upload an image with django and so far i can't see the upload_to directory get created or any file source in the database field.
My Model.
class Person(models.Model):
photo = models.ImageField(upload_to='profiles/', null=True, blank=True)
My View
def create_profile(request):
if request.method == "POST":
form = PartialPersonForm(request.POST, request.FILES,)
addressForm = PartialAddressForm(request.POST)
When i upload and save, i dont get any sort of errors. Anyway i can debug this and find out if the photo field is set.
<div class="photo-upload">{{ form.photo|attr:"onchange:readURL(this);" }}
Unless you're doing something special with regard to media storage, you should set up MEDIA_ROOT to the directory where you want the uploaded files to be saved.
When dealing with file-type fields, you will need to following instructions in the Django documentation for FileField.storage.
In your view, you will need to save() the uploaded form data.
def create_profile(request):
if request.method == "POST":
form = PartialPersonForm(request.POST, request.FILES,)
addressForm = PartialAddressForm(request.POST)
form.save()
addressForm.save()
i believe you should create the upload_to directory yourself. Also make sure to set the appropriate permissions for the directory, otherwise it won't be able to write in it.