I have this code to submit the form:
form = form_class(request.POST, request.FILES, instance=object)
if form.is_valid():
form.save()
image_path = models.ImageField(upload_to='books/')
Currently books/book1/jpg gets inserted into that field.
But I want that the image should be renamed to modelName_pk.jpg and that value gets saved in image_path
How can I achieve that?
Each of the uploaded files are saved to request.FILES which are instances of UploadedFile, so, using the name of the image field in the form you can access it: request.FILES['imagename'].name.
Then you can save the model instance as usual. Hope this helps someone else because this is a very old question
Related
Is there any reason why uploading image file does not work .I have posted this question several times .I will need help for some one to show me the best code practice to upload image file .
If you want the user to be the user who uploads the file, then you can do something like this in your view.
if form.is_valid():
new_file = form.save(commit=False)
new_file.user = request.user
new_file.save()
I'm looking for a way to upload file to django server. The thing is I'm not trying to save in I just to open it and get data for processing. I looked through some of the examples here, but I couldn't find anything that answers this. I'm probably just not looking for a correct thing please help.
I don't want to use models, just a simple website with a upload button.
Thanks!
Use a Form:
class UploadForm(forms.Form):
file = forms.FileField()
def process(self):
file = self.cleaned_data.get('file')
# do whatever you need here to process the file
# e.g. data = file.read()
In your view, call process() on your form after the user uploads the file and the form is successfully validated.
def my_view(request):
if request.method == 'POST':
form = UploadForm(files=request.FILES)
if form.is_valid():
form.process()
return ...
Depending on the size of the file and your Django settings for FILE_UPLOAD_HANDLERS, the file is discarded immediately after the view is done processing if MemoryFileUploadHandler is used. The operating system will also eventually discard the file if TemporaryFileUploadHandler is used.
I have a formset (more specifically a generic inline formset) whose forms have an ImageField. After working around what seems to be a few Django bugs, everything is working fine, except that when I fill the blank form with a new image and click save, the page refreshes after the POST request and the new image is not there. The other fields of the form I just saved are there and are properly filled, but the image URL doesn't show up. The database record is saved correctly and if I simply refresh the page, the image shows up correctly. But I can't figure out how to return from the POST with all the newly saved information without having to refresh the page an extra time.
In case it's relevant, for this ImageField I am using a custom Storage class which handles saving the image in a remote server through an API.
A workaround that solves the problem but which in my opinion shouldn't be necessary:
class ProductImagesView(View):
...
def post(self, request, id):
product = get_object_or_404(Product.objects.by_id(id))
image_formset = ProductImageInlineFormset(
request.POST, request.FILES, instance=product)
if image_formset.is_valid():
image_formset.save()
image_formset = ProductImageInlineFormset(instance=product) # Workaround
return render(...)
You can find more details about my code in this other question:
Django BaseGenericInlineFormSet forms not inheriting FormSet instance as form instance related_object
Any idea why this is happening? Am I doing something wrong or is this a Django bug? Thanks.
UPDATE
One thing I forgot to say: the formset that shows up after saving not only has a blank Image field for the newly created Image object, it also doesn't have the extra blank form for new records that should be there. It also only appears after a refresh.
(I pass extra=1 to the generic_inlineformset_factory):
ProductImageInlineFormset = generic_inlineformset_factory(
Image, form=ProductImageForm, extra=1)
I've posted about this problem before, but I still haven't found a solution so I'm hoping I'll have better luck this time.
I have a form that takes inputted data by the user. In another page, I am creating the identical form that the user has populated (pre-filled with that information) for editing purposes. Users will come to this page to EDIT the information they have already put in. My problem is that it isn't overwriting the instance.
def edit(request):
a = request.session.get('a', None)
if a is None:
raise Http404('a was not found')
if request.method == 'POST':
form = Name_Form(request.POST, instance=a)
if form.is_valid():
j = form.save( commit=False )
j.save()
else:
form = Name_Form( instance = a )
For this form, I'm using "unique_together" for some of the values. I'm also calling on `{{ form.non_field_errors }} in the template.
What is happening is when I make changes in the editing view, if the fields changes involves those defined in "unique_together" then an error is returned telling me that the instance already exists. Otherwise it saves a new instance. It isn't OVERWRITING.
Note that the reason i am using unique_together is that I want to prevent users from initially inputting the same form twice (before the editing stage, in the initial inputting view).
Any ideas?
EDIT: note that "a" refers to a session that includes a drop down box of all the available instances. This carried forward will indicate which instance the user wants to edit.
`
Why not do a database lookup of the model your trying to save and pull the fields from the form to the model then save the model?
Instead to store model a in session you should store it on database. Then edit it:
def edit(request, pk):
a = A.objects.get( pk = pk)
...
pk it the a identifier, you can send it to view via urls.py. I encourage to you to use POST/Redirect/GET pattern.
You can add a 'state' field on your model to control workflow (draft, valid)
You should not save objects in the session. If you really need to use a session - save a PK there and retrieve object right before giving it to Form. But the better solution is to send it in GET or POST parameters or included in url. Sessions are unreliable, data inside it can be destroyed between user's requests.
And you can retrieve value from a session in a more pythonic way:
try:
a = request.session['a']
except KeyError:
raise Http404('a was not found')
Here's the use case:
My main page has an image upload form. When the form is submitted, a page loads with a 4x4 grid of the uploaded image with different photo filters applied. Clicking on an option saves the image with the chosen processing to the database.
My question is, how would I go about doing this without saving to the database until the processing has been chosen?
I'm not opposed to using this problem to learn ajax.
Do it in a single view; There are three possibilities it has to take into consideration:
The user has just arrived on the page - server them an empty form (InitialImageForm)
The user has submitted an image - don't save it, instead create 4 new images and pass them back with a new form (ProcessedImageForm) allowing them to choose one of the generated images
The user has now submitted the final form along with the original image, and the chosen processed image - save it all
This code is a bit messy but it gives you the idea. You would need to write two Forms yourself, along with probably a Model to represent the image and the processed/chosen image
from PIL import Image
def view(self, request):
if request.method=='POST':
# We check whether the user has just submitted the initial image, or is
# on the next step i.e. chosen a processed image.
# 'is_processing_form' is a hidden field we place in the form to differentiate it
if request.POST.get('is_processing_form', False):
form = ProcessedImageForm(request.POST)
if form.is_valid():
# If you use a model form, simply save the model. Alternatively you would have to get the data from the form and save the images yourself.
form.save()
return HttpResponseRedirect('/confirmation/')
elif form.POST.get('is_initial_form', False) and form.is_valid():
form = InitialImageForm(request.POST)
if form.is_valid():
# Get the image (it's not saved yet)
image = Image.open(form.cleaned_data.get('image').url)
processed_list = []
# Create your 4 new images and save them in list
...
# You can show a template here that displays the 4 choices
return direct_to_template(request,template = 'pick_processing.html',extra_context = { 'image' : image, 'processed_list':processed_list })
else:
# When the user arrives at the page, we give them a form to fill out
form = ImageSubmitForm()
return direct_to_template(request,template = 'upload_image.html',extra_context = { 'form' : form })