I have a very basic model with an ImageField on it, and a ModelForm for uploading that image. My form is failing, saying that my image is not valid, but if I instantiate the model's image directly from the request.FILES it works perfectly. The file is uploaded and exists in my media directory. See code below
Also, this is failing in the Admin center as well.
Things I'm pretty sure it is not:
multipart/form-data
incorrect media path settings
permissions settings in those directories.
models.py
class ImageTile(BaseTile):
created_at = models.DateTimeField(default=datetime.datetime.now)
updated_at = models.DateTimeField(auto_now=True)
image = models.ImageField(upload_to='tiles/')
forms.py
class ImageTileForm(forms.ModelForm):
class Meta:
model = ImageTile
fields = ('image', )
views.py
if request.method == 'POST':
# Then we do image tiles
#if request.FILES:
image_form = ImageTileForm(request.POST, request.FILES)
if image_form.is_valid():
image_form.save()
template
<form enctype="multipart/form-data" method="post" action="">
{% csrf_token %}
{{ image_form.non_field_errors }}
{{ image_form.image.errors }}
{{ image_form.image.label_tag }}
{{ image_form.image }}
<button type="submit">Submit</button>
</form>
image_form.errors
django.forms.util.ErrorDict({'image': django.forms.util.ErrorList([u'Upload a valid image. The file you uploaded was either not an image or a corrupted image.' ])})
terminal output from doing it manually
>>> from scrapbook.models import ImageTile
>>> x = ImageTile(image=request.FILES['image'])
>>> x.save()
>>> x.id
2
>>> x.image
<ImageFieldFile: tiles/cathy_orange.jpg>
>>>
Problem was having a PIL install that didn't have jpeg support. Installed libjpeg and re-installed PIL and everything worked great.
Interesting that Django ModelForms validate this but the model does not. The model never threw an error until I tried to access the width/height attributes.
Related
So I have this simple Django application where users can post diary as well as images. Here, uploading image is optional, so I have left the field as not required. The problem is when I leave the ImageField empty. Saving the post w/o image works fine, but when I try to GET the post, I run into the error. First let me show you the code. models.py
class Diary(models.Model):
objects = models.Manager()
# some other stuff here
img = models.ImageField(null=True, blank=True, upload_to="everyday_img")
forms.py
class DiaryInputForm(forms.ModelForm):
# some other stuff here.
img = forms.ImageField(required=False)
views.py
def InputDiary(request):
form = DiaryInputForm(initial={'authuser':request.user})
if request.method == 'POST':
form = DiaryInputForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.authuser = request.user
# some other stuff here
user_img = request.FILES.get('img', None)
instance.save()
return redirect('/diary/diarymain')
return render(request,'diary/diaryinput.html', {'form':form})
def ViewDiary(request, authuser_id, slug):
today = Diary.objects.get(slug=slug)
return render(request, 'diary/diaryview.html', {'today' : today})
diaryview.html
...
<div class="row justify-content-center">
<div class="col col-12">
<div class="detail-contents">
<img src="{{today.img.url}}" class="user-img"><br>
{{today.what|safe}}
</div>
</div>
</div>
...
So when diaryview.html is loaded, the error occurs. I know it's obviously because the img column has no data, but I have no idea on how I should deal with it. Thank you very much in advance. :)
you need to parse the files too from the form
if request.FILES.get('img'):
instance.img= request.FILES.get('img')
also make sure you have MEDIA_URL and MEDIA_ROOT defined in the settings.py file and also url in urls.py file to serve media and static files.
also do this in the html
<img src="{{today.img.url|default_if_none:'#' }}" class="user-img"><br>
I`ve spent a few hours trying to debug this issue. I am trying to import a catalog of product into my app. I am using Django Import-export to import a csv file. I have tried to import it via the admin site and via a simple upload file. In both case, I am encountering some errors. Would you have an idea how to resolve them?
1st Method: Import the csv file via the admin site
Error encountered: Imported file has a wrong encoding: 'charmap' codec can't decode byte 0x9d in position 13365: character maps to
It looks like this method cannot accept some character(""). How can I change my code to accept any character? I`ve already removed the following characters: £, - and try to encode it in UTF-8. I have also done a search to remove every non ASCII characters(128-255)
2eme Method: Import the csv file via the website
Error encountered: 'MultiValueDict' object is not callable
views.py
def simple_upload(request):
if request.method == 'POST':
file_format = request.POST.get('file-format')
product_resource = ProductResource()
dataset = Dataset()
new_products = request.FILES['Price_List']
if file_format == 'CSV':
imported_data = dataset.load(new_products.read().decode('utf-8'),format='csv')
result = product_resource.import_data(dataset, dry_run=True)
elif file_format == 'JSON':
imported_data = dataset.load(new_products.read().decode('utf-8'),format='json')
# Testing data import
result = product_resource.import_data(dataset, dry_run=True)
if not result.has_errors():
# Import now
product_resource.import_data(dataset, dry_run=False)
return render(request, 'catalog/simple_upload.html')
models.py
from import_export import resources
from .models import Product
class ProductResource(resources.ModelResource):
class Meta:
model = Product
skip_unchanged = True
report_skipped = False
simple_upload.html
{% extends 'base.html' %}
{% block body %}
<h3>Import Data</h3>
<p>importing to database</p>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="importData">
<p>Please select format of file.</p>
<select name="file-format" class="form-control my-3">
<option selected>Choose format...</option>
<option>CSV</option>
<option>JSON</option>
</select>
<button class="btn btn-primary" type="submit">Import</button>
</form>
{% endblock %}
Many Thanks,
I have a model like this:
class Assignment(models.Model):
content = models.FileField(upload_to='xxx')
other_val = models.CharField(...) # not important
And a form wrapping this model (ModelForm):
class AssignmentForm(ModelForm):
class Meta:
model = Assignment
fields = ['content', 'other_val']
My view looks like this (for simplicity I skip the request.POST/request.FILES. part):
#login_required(login_url='/login/')
def create_assignment(request):
form = AssignmentForm()
# render form
#login_required(login_url='/login/')
def update_assignment(request, assignment_id):
assignment = Assignment.objects.get(id=assignment_id)
form = AssignmentForm(instance=assignment)
Creating an assignment works just fine - It forces me to upload a file, which is what I want. But when I want to update the content of the assignment (the file), it first shows a link of a previously uploaded file (excellent!) then the upload button, like this:
Currently: AssignmentTask_grading_script/grading_script_firing.py
Change: [Choose File] no file chosen
But then I assume if I don't want to replace this file, I should simply click the submit button. Unfortunately, when I click the submit button, the form complains that I should upload a file. Is there a way to silent the complaint if a file is already in database?
As following the previous comments, maybe like this;
1. forms.py
class AssignmentForm(forms.ModelForm):
# as following #Rohan, to make it optional.
content = forms.FileField(required=False)
class Meta:
model = Assignment
fields = ['content', 'other_val']
2. yourtemplate.html
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
<script>
{% if not form.content.value %}
$('#id_content').attr({'required': 'required'});
{% endif %}
</script>
The field of content is under required only if havn't value before...
I have three mysql tables without pk’s assigned, table A contains unique names, B contains distinct names and value 1 (longer than table 1), and table C is distinct values of names, value 1 and value 2 (longer than table B). I am struggling to define models and form for these relationships to create a form (Django form or html select form) to do what django smart_selects promises to do. https://github.com/digi604/django-smart-selects, I have followed the documentation and many answers on the net. But my app is still not working. here is my code:
there may be typo's or spacing issues on this post, but those are not the cause of errors in my app.
I am using python 2.7, django 1, 10, 0
smart_selects is added to settings, project url (not app url), etc.
models.py
class Names(models.Model):
name = models.CharField(max_length=150, unique=True)
class Meta:
db_table = 'A'
class Foo(models.Model):
Name = models.ForeignKey(Names, to_field = 'name', db_column='name')# need to assign db_column or get error Name_id in fieldlist, it is possible that “to_field” is not needed here. But I am not sure
Val1 = models.BigIntegerField(blank=True, null=True)
class Meta:
db_table = 'B'
class Foo2(models.Model):
name = models.ForeignKey(Names, db_column='name', to_field="name", related_name = 'name_')
VAL1 = ChainedForeignKey(Foo, chained_field="name", chained_model_field="Name", db_column='val1')#again, need to define db_column name or get error VAL1_id not in field list
class Meta:
db_table = 'C'
forms.py -not currently using this form, please see view and html.
class SearchForm(ModelForm):
class Meta:
model = Foo2
fields = '__all__'
#The form left like is will render empty select boxes. I have to define
def __init__(self, *args, **kwargs):
super(SearchForm, self).__init__(*args, **kwargs)
self.fields['name'] = forms.ModelChoiceField(Foo2.objects.all().values_list('name', flat=True))
#other form lines removed.
and view.py
def index(request, name):
value = Foo2.objects.all().values('names', 'VAL1')
return render(request, 'index.html', {'form':value})
html
<form action="" method="POST">{% csrf_token %}
<h3>Filters</h3>
{% if form %}
<select>
{% for co in form %}
<option value="{{ co.names }}">{{ co.names }}</option>
{% endfor %}
</select>
<br>
<select>
{% for co in form %}
<option value="{{ co.VAL1 }}">{{ co.VAL1 }}</option>
{% endfor %}
</select>
{% endif %}
<br>
<input type="submit" value="Submit" class="submit" name="submit">
</form>
After writing the code, I have run:
Python manage.py makemigrations app_name
Python manage.py migrate --fake app_name
The application works, but the VAL1 select box is not filtered (smart_select functionality is not working). What I need to know if there is something wrong in my design of the models/apps.
thank you
I have the same problem. Apparently, smart_selects cannot handle ForeignKeys with 'to_field'. Also, try accessing the admin page and see if the dropdown menus work there. What I did was to do the tutorial exactly in a test app, see if smart_selects works for the test models, and then plug in my models to see if they would.
In my case, the test models worked but my own models didn't -- but removing the 'to_field' made it work. I'll be reading the source code and see if I can find a workaround.
I'm using django-imagekit to resize my user avatars and right now to display a default avatar (if the user didn't upload his/her avatar) I do this:
views.py
try:
usr_avatar = UsrAvatar.objects.get(user=request.user.id)
except UsrAvatar.DoesNotExist:
usr_avatar = UsrAvatar.objects.get(id='0')
template.html
<img src="{{ usr_avatar.avatar_image.url }}" >
This works fine but every time a user didn't upload his/her avatar I'm hitting the database for the default avatar image.
Is there a way to eliminate hitting the database when the user doesn't have an avatar image loaded by somehow attributing the default image link to usr_avatar or just doing something in the template.html? Thank you!
Apt username given your question!
You could create a context processor that provides the default avatar to every template and simply make sure that the context processor caches the image
settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
...
'myapp.context_processors.default_avatar',
...
)
myapp/context_processors.py
from django.core.cache import cache
def default_avatar(request):
default_avatar = cache.get('default_avatar', False)
if not default_avatar:
default_avatar = UsrAvatar.object.get(id='0')
return {
'default_avatar' : default_avatar
}
Now the template variable 'default_avatar' is available in every template:
{% if usr_avatar %}
{{ usr_avatar }}
{% else %}
{{ default_avatar }}
{% endif %}
Alternatively just use the cache in your original query:
try:
usr_avatar = UsrAvatar.objects.get(user=request.user.id)
except UsrAvatar.DoesNotExist:
usr_avatar = cache.get('default_avatar', False)
if not usr_avatar:
usr_avatar = UsrAvatar.objects.get(id='0')
But Finally, it might be even better to avoid keeping the default avatar in the database at all and instead just write a context processor like above but instead of getting the default avatar from the DB, just have a static url to the image
from django.conf import settings
def default_avatar(request):
return {
'default_avatar' : '%simages/default_avatar.jpg' % settings.STATIC_URL
}