update forms.FileField on django forms - django

I have a model with a FileField in it:
class DocumentUpload(models.Model):
document_name = models.CharField(max_length=100, blank=True)
document_path = models.FileField(upload_to='uploads')
and a form which uses this model
class DocumentUploadForm(forms.ModelForm):
class Meta:
model = DocumentUpload
When I use the form to create a new upload everything works fine.
if request.method == 'POST':
form = DocumentUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
However when I try and update/edit the entry it updates all the fields apart from the document which is uploaded. This just stays the same as the original upload.
d = get_object_or_404(DocumentUpload, pk=id)
if request.method == 'POST':
form = DocumentUploadForm(data=request.POST, files=request.FILES, instance=d)
if form.is_valid():
u = form.save()
How do I get it to change the upload file when editing the instance?
Thanks

Since it was my idea, I'll post it up as an answer (just to stroke my own ego and/or rating)...
Add the following to your form's template:
enctype="multipart/form-data"
feel free to check it off as an answer...
:)

just needed to add:
enctype="multipart/form-data"
to my form. Thanks Brant

Related

django update form has no attribute save

I am trying to create a form which will allow users to update their name, I am using a forms.form instead of ModelForm because it gives you more control over the styling of the form because you can use widgets. when I go to save the form it says that updateNameForm has no attribute save
view
def UpdateName(request,user_id):
if request.method == "POST":
form = UpdateNameForm(request.POST,initial=initial)
if form.is_valid():
name = form.cleaned_data['name']
form.save()
else:
form = UpdateNameForm(initial=initial)
forms.py
class UpdateNameForm(forms.Form):
name = forms.CharField(
required=True,
label="*Status",
widget=forms.widgets.Select(attrs={'class' : 'span6 small-margin-top small-margin-bottom'})
)
A standard form class indeed has no save attribute - it doesn't know anything about any models to save to. You need to use a ModelForm.
Note also you need to pass the instance argument to the form to make it update an existing instance, rather than create a new one. You probably don't need initial at all.
def UpdateName(request,user_id):
user = get_user(user_id)
if request.method == "POST":
form = UpdateNameForm(request.POST,initial=initial)
if form.is_valid():
name = form.cleaned_data['name']
user.name = name
user.save()
else:
form = UpdateNameForm(initial=initial)

Update object with model form inside the view

I need to update the object with its model form and passed the instance as described in the django doc. However I am having these problems when saving the form:
When I change the title and submit the form, it gives me an error that the image field is required and image field gets blank. However when the image is changed, the title field is not blank and it does not give any error.
If everything works and submits the form, it creates a new snap object instead of updating the instance object.
In the views I tried using both the obj.save() and obj.update(), but nothing helped. Please help me how to solve this problem. I will really appreciate your help Thank you.
form:
class SnapForm(forms.ModelForm):
class Meta:
model = Snap
fields = ['title', 'description', 'image', 'upload_date']
view:
def admin_snap_settings(request, snap_id):
if not request.user.is_admin:
return render(request, 'admin_login_invalid.html')
else:
instance = Snap.objects.get(id=snap_id)
if request.user == instance.user:
if request.method == "POST":
form = SnapForm(request.POST, request.FILES, instance=instance)
if form.is_valid():
form.save()
return HttpResponseRedirect('/custom123user/admin/snapview')
else:
form = SnapForm(instance=instance)
return render(request, 'admin_snap_settings.html', {
'form': form
})
else:
return render(request, 'wrong_user.html')
After hours of debugging and scratching head... I realized that the url of the action for the form was pointing to admin_snap_add() view and not to the admin_snap_settings() view.
Hope this will help someone so dumb as me. If you guys want me to delete this question please inform me. Thank you for your time.

How to extract File Object from Django Form FileField

I have created a ModelForm with fields, title, file and content. Here file is a FileField(). But I can't call the save() method of this form due to some reasons. So I have to maually created one Model Object and assign cleaned values to that object. Everything worked excpt that FileField. The file is not saving. How can I fix this? Is it the correct method to extract FileField?
Form
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ('title','file', 'content',)
Views.py
form = TestForm(request.POST,request.FILES)
if form.is_valid():
content = form.cleaned_data['content']
file = form.cleaned_data['file']
title = form.cleaned_data['title']
fax = Fax()
fax.title = title
fax.file = file
fax.content = content
fax.save()
Here the file is not saving. How can I fix this?
Any help will be appreciated!
Have u used enctype="multipart/form-data" in your form
Seems like the code is fine.
Please using this type of validation. This may work
if request.method == 'POST':
form = ModelFormWithFileField(request.POST, request.FILES)
if form.is_valid():
# file is saved
form.save()
return HttpResponseRedirect('/success/url/')``
I think you can use
request.FILES['file']
for getting the file object

form instance of a model gives id=None Django

I'm misunderstanding something! If my model is not saved, it does not have an id associated with it. So if I have something like this:
views.py (inserting or editing existing info uses the same modelform)
def insert_or_modify(request, id=None):
if id is not None:
book = BookModel.objects.get(pk=id)
else:
book = BookModel()
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES, instance=book)
if form.is_valid():
form.save()
....
return render_to_response(...)
I also have an image and use upload_to for the imagefield. There are two problems: id is None and I'm not sure how to manipulate/save the instance=book so that I would actually get an id. The second problem is the location I save my data to is way off. Even though the template tag book.img.url has the desired location of the book at http:127.0.0.1:8000/folder1/media/id/, the actual location is somewhere else:
Where I want to save my image to:
/project/folder1/media/id/
where id is the book id.
What I actually get:
/project/id/
(But 'id' becomes 'None' since it doesn't exist!)
My previous code worked. It would save to the correct location, but with this current code, it doesn't work. So the saving issue doesn't seem like it's due to settings.py since it worked previously.
EDIT: removed non-code from code formatting area
EDIT: I found out why I wasn't saving to the correct location. As it turned out, I forgot to uncomment something when I last modified settings.py. Saving to the location works now! Sorry guys!
EDIT: I think the id=None problem is caused by form.save(). If I avoid doing that and just save to the model directly, I don't have this problem.
Id assigns only on saving objects when you use autoincrement id field (default).
You can save item before handling image, and then save image.
May be you can not worry about image name - becouse django file storages dont have troubles with same image names. So if you just save file "image.png", and then save another file with name "image.png" - then it will be saved as "image_1.png"
def add_or_create(request, item_id=None):
item = get_object_or_404(BookModel, id=item_id) if item_id else None
form = BookInfoForm(request.POST or None, request.FILES or None, instance=book) # assume it is ModelForm
if form.is_valid():
book = form.save()
For the first part:
def insert_or_modify(request, id=None):
if id:
book = BookModel.objects.get(pk=id)
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES, instance=book)
if form.is_valid():
save_book = form.save()
# use save_book as your instance of BookModel
....
else:
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES)
if form.is_valid():
save_book = form.save()
# use save_book as your instance of BookModel
....
save_book = form.save() allows you to then use save_book as your saved instance of BookModel, and save_book.id is its id.
def create_id(instance,some_id=None):
if some_id is None:
obj=Post.objects.first()
new_id=obj.id
new_id+=1
return new_id
else:
return some_id
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.id:
instance.id = create_id(instance)
pre_save.connect(pre_save_post_receiver, sender=Post)

How to edit/add objects using the same django form?

Hey, I've searched around to do this (particularly this Q: Django edit form based on add form?) but I just can't get it to work.
The problem I'm having is that the form always creates a new object, instead of modifying the existing one.
This is my code:
def new_task(request, task_id=None):
if task_id is not None:
task = Task.objects.get(pk=task_id)
else:
task = Task()
if request.method == 'POST': # If the form has been submitted...
form = TaskForm(request.POST, instance=task)
if form.is_valid():
form.save();
return tasks(request, 'Task #%s created successfully.' % (task.id))
else:
form = TaskForm(instance=task)
return custom_render('user/new_task.html',
{'form': form},
request);
Any clues on what I'm missing? Thanks
Edit: added form definitions.
class TaskForm(ModelForm):
description = CharField(max_length = 1500,
widget= forms.Textarea(attrs={'class':'task-description'}),
required=True)
class Meta:
model = Task
Ok, after a nice night of debugging i found out what the problem was. Quite stupid actually.
The problem was that on submit, task_id was None.
I worked it out by doing:
On the form I added: <form action="{% url App.myapp.views.new_task **task_id** %}"
On my views I added:
return custom_render('user/new_task.html',
{'form': form, 'submit': submit, 'task_id':task.id},
request)
That was it. A newbie mistake. If someone out there knows a nicer way I'm open to suggestions.