How can I let users upload images to photologue? - python

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.

Related

Django download file button takes in path

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/

save form imagefield to another image field in view in django

I have the following view which saves one image field to another before saving:
if request.method == 'POST':
form = PlayerForm(request.POST, request.FILES, instance=current_player)
if form.is_valid():
temp_image = form.cleaned_data['profile_image2']
form.cleaned_data['profile_image'] = temp_image
form.profile_image = temp_image
form.save()
return redirect('player')
The problem is that the image does not save. I'm using boto as a backend. I'm not sure if this has anything to do with it.
How do I get the temp image to save to the profile image?
I think you might want to save the form to a model first and update profile_image after that:
from django.core.files.base import ContentFile
if form.is_valid():
new_player = form.save()
temp_image = new_player.profile_image2
# duplicate the image for "profile_image2"
dup_file = ContentFile(temp_image.read())
dup_file.name = temp_image.name
new_player.profile_image = dup_file
new_player.save()
Your code is a bit confusing to me. As I understood is that you're taking the image from profile_image2 and assigning it to profile_image field? If that is what you are trying then this would be a possible answer:
image = form['profile_image2']
photo = PlayerForm(profile_image=image)
photo.save()
[Beginner here so there might be a slight mistake, but that's how would I go about and solve this question, if I was doing what you are doing]

Passing form data from my view to thank you page

Is there a way I can pass data from a form submission over to the 'thank you' page. The reason i'd like to do this is because I have a form on the website, where the user will select multiple fields which all contains different PDF's.
So once the user has submitted the form the idea is to re-direct them to a thankyou page, where they can view the list of pdf/files they have selected on the form.
I hope this is enough info to go on. Here are my views / models.
def document_request(request, *args):
# template = kwargs['name'] + ".html"
if request.method == 'POST':
form = forms.ReportEnquiryForm(request.POST)
print(request.POST)
if form.is_valid():
docrequest = form.save()
return HttpResponseRedirect(reverse('thank_you', kwargs={'id': docrequest.id}))
else:
form = forms.ReportEnquiryForm()
return render_to_response('test.html',{'form':form})
def thank_you(request):
docrequest = DocumentRequest.objects.get(pk=id)
return render_to_response('thankyou.html',
{'docrequest' : docrequest },
context_instance=RequestContext(request))
My initial idea was to pass the data to a new view called thank_you. But not this is possible.
class DocumentUpload(models.Model):
name = models.CharField(max_length="200")
document_upload = models.FileField(upload_to="uploads/documents")
def __unicode__(self):
return "%s" % self.name
class DocumentRequest(models.Model):
name = models.CharField(max_length="200")
company = models.CharField(max_length="200")
job_title = models.CharField(max_length="200")
email = models.EmailField(max_length="200")
report = models.ManyToManyField(DocumentUpload)
def __unicode__(self):
return "%s" % self.name
form.py
class ReportEnquiryForm(forms.ModelForm):
class Meta:
model = models.DocumentRequest
fields = ('name', 'company', 'job_title', 'email', 'report')
If you need anymore info, please ask :)
You've saved the user's submission in a DocumentRequest object. So you can pass the ID of that object in the URL when you redirect, and in the thank_you view you can get the DocumentRequest and render the list.
Edit The idea is to make the thank_you page like any other view that accepts a parameter from the URL:
url(r'thanks/(?P<id>\d+)/$, 'thank_you', name='thank_you')
and so the POST part of the form view becomes:
if form.is_valid():
docrequest = form.save()
return HttpResponseRedirect(reverse('thank_you', kwargs={'id': docrequest.id}))
and thank_you is:
def thank_you(request, id):
docrequest = DocumentRequest.objects.get(pk=id)
return render_to_response('thankyou.html',
{'docrequest' : docrequest },
context_instance=RequestContext(request))
Second edit
As others have suggested, this makes it possible for anyone to see the request. So a better solution is to put it in the session:
docrequest = form.save()
request.session['docrequest_id'] = docrequest.id
and in thank_you:
def thank_you(request):
if not 'docrequest_id' in request.session:
return HttpResponseForbidden
docrequest = DocumentRequest.objects.get(request.session['docrequest_id'])
You can do as Daniel Roseman said but in this case the thank you pages can be accessed by anyone with the Ids.
Some ways to pass data between views are the following(the list is not mine.):
GET request - First request hits view1->send data to browser -> browser redirects to view2
POST request - (as you suggested) Same flow as above but is suitable when more data is involved
Using django session variables - This is the simplest to implement
Using client-side cookies - Can be used but there is limitations of how much data can be stored.
Maybe using some shared memory at web server level- Tricky but can be done.
Write data into a file & then the next view can read from that file.
If you can have a stand-alone server, then that server can REST API's to invoke views.
Again if a stand-alone server is possible maybe even message queues would work.
Maybe a cache like memcached can act as mediator. But then if one is going this route, its better to use Django sessions as it hides a whole lot of implementation details.
Lastly, as an extension to point 6, instead of files store data in some persistent storage mechanism like mysql.
The simplest way is to use sessions. Just add the id to the session and redirect to the thank you view, you read the id value and query the db with that id.

Django SimpleLazyObject

When I try to submit, I get a TypeError:
int() argument must be a string or a number, not 'SimpleLazyObject'
My views.py:
def bookmark_save_page(request):
if request.method == 'POST':
form = BookmarkSaveForm(request.POST)
if form.is_valid():
# Create or get link.
link, dummy = Link.objects.get_or_create(
url=form.cleaned_data['url']
)
# Create or get bookmarks.
bookmark, created = Bookmark.objects.get_or_create(
user = request.user,
link = link
)
# Update bookmark title.
bookmark.title = form.cleaned_data['title']
# If the bookmark is being updated, clear old tag list.
if not created:
bookmark.tag_set.clear()
# Create new tag list.
tag_names = form.cleaned_data['tags'].split()
for tag_name in tag_names:
tag, dummy = Tag.objects.get_or_create(name=tag_name)
bookmark.tag_set.add(tag)
# Save bookmark to database.
bookmark.save()
return HttpResponseRedirect(
'/user/%s/' %request.user.username
)
else:
form = BookmarkSaveForm()
variables = RequestContext(request, {'form': form})
return render_to_response('bookmark_save.html',variables)
Please guide me.
Thank you.
request.user, by default is of type SimpleLazyObject. To resolve it,
bookmark, created = Bookmark.objects.get_or_create(
user = request.user,
link = link
)
should be
bookmark, created = Bookmark.objects.get_or_create(
user = request.user.id,
link = link
)
If this does not resolve it, make sure you are logged in.
There is another option, may be this solution will help you fix it.
from django.contrib import auth
bookmark, created = Bookmark.objects.get_or_create(
user = auth.get_user(request),
link = link
)

ImageField Upload with Django

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.

Categories

Resources