Im working on web app project for study. I have a problem with file upload.
It works for an admin, but for regular user files don't save. It must be a problem with mu views.py or template html
forms.py
class DocumentUpload(forms.ModelForm):
class Meta:
model = Form
fields = ('file',)
models.py
class Form(TimeStampedModel, TitleSlugDescriptionModel):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=512)
is_final = models.BooleanField(default=False)
is_public = models.BooleanField(default=False)
is_result_public = models.BooleanField(default=False)
file = models.FileField(null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('form-detail', kwargs={'slug': self.slug})
views.py
def create_form(request):
if request.method == 'POST':
user = request.user
data = ParseRequest(request.POST)
print(data.questions())
print(data.form())
parsed_form = data.form()
parsed_questions = data.questions()
# tworzy formularz o podanych parametrach
formfile = DocumentUpload(request.POST, request.FILES or None)
if formfile.is_valid():
form = formfile.save(commit=False)
print(form)
form.author = user
form.title = parsed_form['title']
form.is_final = parsed_form['is_final']
form.is_result_public = parsed_form['is_result_public']
form.description = parsed_form['description']
form.save()
# zapisuje pytania z ankiety wraz z odpowienimi pytaniami
for d in parsed_questions:
question = Question(form=form, question=d['question'])
question.save()
# dla kazdego pytania zapisz wszystkie opcje odpowiadania
for opt in d['options']:
option = Option(question=question, option=opt)
option.save()
return render(request, 'forms/form_form.html', {})
else:
form = DocumentUpload()
return render(request, 'forms/form_form.html', {'form': form})
create_form.html
{% block content %}
<form method="post" id="form" enctype='multipart/form-data'>
{%csrf_token %}
<div class="form-group">
{% csrf_token %}
<label for="form-title">Tytuł formularza</label>
<input id="form-title" class="form-control" type="text"
placeholder="Tytuł" required/>
</div>
{{ form.as_p }}
<input class="btn btn-default" type="submit" value="zapisz"/>
</form>
{% endblock %}
5.settings.py
....
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
...
5.urls.py
if settings.DEBUG:
urlpatterns +=
static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
You forgot to add action on your form just like so :
<form action="{% url 'name_of_your_function' %}" method="post" id="form" enctype='multipart/form-data'>
...
</form>
action must contain your url name, example :
url(url_regex, views.function, name="name_of_your_function"),
You haven't specified an upload_to attribute for your FileField in models.py.
Add a directory for your field, like,
file = models.FileField(upload_to='uploads/', null=True, blank=True)
Your form is all fine and the file has been sent through request, but Django does not know where to save the file, until you define it in your models.
Read more about it in the docs here
Related
I have a simple app that uses an ImageField to upload & store a photo. I'm running the app local. The form displays as expected, and allows me to browse and select a jpg file. It then shows the selected filename next to the "Choose File" button as expected. When I submit the form, it saves the model fields 'name' and updates 'keywords' but it does not save the file or add the filename to the db. No errors are generated. Browsing the db, I see the newly added record, but the 'photo' column is empty. Any help appreciated.
settings.py:
MEDIA_ROOT = '/Users/charlesmays/dev/ents/ents/enrich/'
models.py:
class Enrichment(models.Model):
name = models.CharField( max_length=255, unique=True)
keywords = models.ManyToManyField(KeyWord, blank=True)
photo = models.ImageField(upload_to='enrichments/', null=True, blank=True)
views.py:
def EnrichmentUploadView(request):
if request.method == 'POST':
form = CreateEnrichmentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('index'))
else:
return render(request, 'createEnrichment.html', {'form':form})
else:
form = CreateEnrichmentForm()
return render(request, 'createEnrichment.html', {'form':form})
forms.py:
class CreateEnrichmentForm(forms.ModelForm):
class Meta:
model = Enrichment
fields = ('name', 'photo', 'keywords')
enctype="multipart/form-data"
template:
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
Change all these, then it should work..
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
-------
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
models.py
photo = models.ImageField(upload_to="enrichments/", default="")
And your template form
<form action="" id="" method="" enctype="multipart/form-data">
------
</form>
Problem is that image is not saving. when I am select an image and upload all the code working properly but the image does not save. I checked all the code line by line I do not understand what's the problem. I also see the media file any image is saved or not, but the image wasn't saved.
this is models.py in this file I use the image field
models.py
class Answer (models.Model):
question=models.ForeignKey(Question,on_delete=models.CASCADE)
user=models.ForeignKey(User,on_delete=models.CASCADE, null=True)
img=models.ImageField(null=True,blank=True,upload_to='Answer_Img')
detail=RichTextUploadingField()
add_time=models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.detail
forms.py
class AnswerForm(ModelForm):
class Meta:
model=Answer
fields=('detail','img')
labels={'img':'Upload Image'}
views.py
def answer(request,pk,slug):
try:
trend=Question.objects.get(pk=pk,slug=slug)
except:
raise Http404("Post Does Not Exist")
tags=trend.tags.split(',')
ans=Answer.objects.filter(question=trend)
answerform=AnswerForm
if request.method=='POST':
answerData=AnswerForm(request.POST)
if answerData.is_valid():
answer=answerData.save(commit=False)
answer.question=trend
answer.user=request.user
answer.save()
p=messages.success(request,'Answer has been submitted.')
return HttpResponseRedirect(trend.slug)
return render(request,"ask/answer.html" ,{
'trends':trend,
'tags':tags,
'answer':ans,
'form':answerform,
})
answer.html
{% if user.is_authenticated %}
<div class="container">
<div class="py-5 text-center bg-secondary text-white">
<h1 class="mb-3">Upload Image</h1>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form}}
<input type="submit" class="btn btn-danger" value="Upload">
</form>
</div>
{% else %}
<h3><P>Sign In/Sign Up before posting answers</P></h3>
<h4><li>Sign In</li><h4>
<h4> <li>Sign Up</li><h4>
{% endif %}
settings.py
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
urls.py
urlpatterns = [
# my url patterns here
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
Use request.files to get the img. please check if the media folder is in your base directory and the subfolder is named correctly.
if request.method == "POST":
answer_form = Answer_form(data=request.POST)
if(answer_form.is_valid()):
ans = answer_form.save(commit=False)
#ans.user = user
if 'img' in request.FILES:
ans.img = request.FILES['img']
ans.save()
else:
print(answer_form.errors)
Here is the documentation page :
File Uploads
When I use the form provided by django admin everything works fine. But after creating my own form, django does not write data to my model. Is something missing in my code?
Models.py
class Offert(models.Model):
name = models.CharField(max_length=50)
file = models.FileField(upload_to='app/documents/')
forms.py
class OffertFormCV(forms.ModelForm):
class Meta:
model = Offert
fields = ( 'name',
'file')
views.py
def my_views(request):
if request.method == 'POST':
form = OffertFormCV(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('app:thank_you_page'))
else:
form = OffertFormCV()
context = {'form': form}
return render(request, 'form_application.html', context)
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app.urls', namespace='app'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'app/media')
form_application.html
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Send</button>
</form>
After sending the form, nothing happens. Any help will be appreciated.
You need to add enctype="multipart/form-data" to your form to be able to upload files:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Send</button>
</form>
I have an image field on a model that i'd like to render inside an img tag. It's inside of a formset and I can see the link to the image, but if I try to reference form.image.url nothing comes back. form.image returns "Current :" "" which breaks because of the leading string. How can get the images to display?
Stack
Django 2.1, django-storages using S3
Storages Settings
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_DEFAULT_ACL = 'None'
AWS_S3_REGION_NAME = "us-east-1"
AWS_LOCATION = "images"
AWS_STORAGE_BUCKET_NAME = 'fakebucketname'
MEDIA_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
AWS_S3_HOST = 's3.us-east-1.amazonaws.com'
AWS_DEFAULT_ACL = None
Models
class Note(models.Model):
user = models.CharField(null=True, max_length=25)
image = models.ImageField(upload_to="%Y/%m/%d/")
text = models.TextField(verbose_name='Text', null=True)
pub_date = models.DateTimeField(auto_now_add=True)
report = models.ForeignKey(Report, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.user
class Report(models.Model):
name = models.DateField(auto_now_add=True, unique=True, verbose_name='Report Name')
slug = models.SlugField(blank=True)
def __str__(self):
return str(self.name)
def __unicode__(self):
return u"%s" % self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
return super(Report, self).save(*args, **kwargs)
def get_absolute_url(self):
from django.urls import reverse
return reverse('report_detail', args=[str(self.id)])
Forms
from TheDaily.models import Report, Note
from django.forms import ModelForm, inlineformset_factory
class NoteForm(ModelForm):
def __init__(self, *args, **kwargs):
super(NoteForm, self).__init__(*args, **kwargs)
self.fields['image'].required = False
class Meta:
model = Note
exclude = ()
class ReportForm(ModelForm):
class Meta:
model = Report
fields = '__all__'
NoteFormset = inlineformset_factory(Report, Note, form=NoteForm, extra=1)
View
def manage_reports(request, pk):
class Media(object):
js = formset_media_js + (
)
report = Report.objects.get(pk=pk)
note_inline_form_set = inlineformset_factory(Report, Note, extra=2,
fields=('user', 'category', 'text', 'report', 'image'),
widgets={'text': forms.Textarea(attrs={'class': 'form-control'}),
'user': forms.TextInput(attrs={'class': 'form-control'}),
'image': forms.ClearableFileInput,
'category': forms.Select(attrs={'class': 'form-control'})})
if request.method == "POST":
formset = note_inline_form_set(request.POST, request.FILES, instance=report)
if formset.is_valid():
for form in formset:
form.cleaned_data['user'] = request.user.username
formset.save()
return HttpResponseRedirect('/')
else:
formset = note_inline_form_set(instance=report)
return render(request, 'daily/report.html', {'formset': formset})
Template
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{% load formset_tags %}
<div id="formset" data-formset-prefix="{{ formset.prefix }}">
{{ formset.management_form }}
<div data-formset-body>
<!-- New forms will be inserted in here -->
{% for form in formset %}
<div data-formset-form>
{{ form.as_p }}
<img id="image_preview"src="{{ form.image.url }}"/>
</div>
{% endfor %}
</div>
<!-- The empty form template. By wrapping this in a <script> tag, the
__prefix__ placeholder can easily be replaced in both attributes and
any scripts -->
<script type="form-template" data-formset-empty-form enctype="multipart/form-data">
{% escapescript %}
<div data-formset-form>
{{ formset.empty_form }}
</div>
{% endescapescript %}
</script>
<!-- This button will add a new form when clicked -->
<input type="button" value="Add another" data-formset-add class="btn btn-w-md btn-info">
<input type="submit" value="Submit" class="btn btn-w-md btn-accent"/>
<script>jQuery(function ($) {
$("#formset").formset({
animateForms: true
});
});</script>
</div>
</form>
Django ModelForm ImageField
I went with the 2nd option and made the NonClearableImageInput widget. Seems to be working well
I have already tried searching stackoverflow, but couldn't find anything. My problem is that I cannot seem to find the folder where the pictures I upload is supposed to be. Seems like everything else works?
Here you can see my code:
Settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Views.py
#login_required(login_url="/login/")
def model_form_upload(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES,instance=request.user)
if form.is_valid():
form.save()
print("Form is valid")
return redirect('/questions/profile')
else:
form = DocumentForm(instance=request.user)
return render(request, 'questions/model_form_upload.html', {
'form': form
})
Urls.py
url(r'^upload/$', views.model_form_upload, name='upload')
Models.py
import os
def get_image_path(instance, filename):
return os.path.join('users/', str(instance.id), filename)
class Document(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile_image = models.FileField(upload_to=get_image_path,
blank=True, null=True)
Forms.py
from questions.models import Document
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('profile_image',)
model_form_upload.html
{% extends 'questions/base.html' %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
<p>Return to profile</p>
{% endblock %}