auto generate thumbnail for FileField in django - django

I uploaded different file types to my project(pdf,doc,mp4 ,jpg).
now I want to auto-generate thumbnail for each file which is going to add or was added previously, and save it to my DB.
here is what I think:
here is my File model:
class File(models.Model):
slug = models.SlugField(
max_length=255,
unique=True,
)
address = models.FileField(
validators=[
file_size,
FileExtensionValidator(
allowed_extensions=[
"jpg",
"mp4",
"doc",
"pdf",
]
),
],
upload_to="files/",
max_length=255,
)
thumbnail = models.ImageField(
upload_to="files/thum/", max_length=255, null=True, blank=True
)
TYPES = [
(IMG, "Image"),
(VID, "Video"),
(DOC, "Document"),
]
type = models.CharField(max_length=3, choices=TYPES, default=IMG)
here I wrote a function :
from io import StringIO
from PIL import Image
def make_thumbnail(file):
if file.type == File.IMG:
make_image_thumbnail(file)
if file.type == File.VID:
make_video_thumbnail(file)
if file.type == File.DOC:
make_document_thumbnail(file)
def make_image_thumbnail(file):
img = Image.open(file.address)
img.thumbnail((128, 128), Image.ANTIALIAS)
thumbnailString = StringIO()
img.save(thumbnailString, "JPEG")#error : string argument expected, got 'bytes'
newFile = InMemoryUploadedFile(
thumbnailString, None, "temp.jpg", "image/jpeg", thumbnailString.len, None
)
return newFile
def make_video_thumbnail(file):
video_input_path = file.address
file_name = file.slug + "thumbnail"
img_output_path = os.path.join(settings.MEDIA_ROOT, file_name)
subprocess.call(
[
"ffmpeg",
"-i",
video_input_path,
"-ss",
"00:00:00.000",
"-vframes",
"1",
img_output_path,
]
)
def make_document_thumbnail(file):
# cache_path = ?
# pdf_or_odt_to_preview_path = file.address
# manager = PreviewManager(cache_path, create_folder=True)
# path_to_preview_image = manager.get_jpeg_preview(pdf_or_odt_to_preview_path)
pass
now I want to fill the functions and I don't know
a) how can I auto-generate it
b) how can I generate thumbnail for image and doc?( I tested these libs but I was confused totally)
preview-generator and also django-thumbnails
(for the files which I added I planed to write a migration and run it. is there any better idea?)

Related

Django | Decimal Field is required even tho i set it to NULL=True

im trying to play a little bit around with django but i have run into problems...
I have a Decimal Field which is not required so i set it to "blank=True" and "null=True". But it still says its required :(
I also did all the migrations.
Here is my models.py
from django.db import models
weightUnit = {
('kg' , 'kilogram'),
('g', 'gram'),
('t', 'tons'),
('n', '-'),
}
class Product(models.Model):
pname = models.CharField(
max_length=50,
)
pdesc = models.TextField(
max_length=5000,
)
pprice = models.DecimalField(
max_digits=6,
decimal_places=2,
)
psn = models.CharField(
max_length = 30,
null=True,
blank=True,
)
pweightunit = models.CharField(
choices=weightUnit,
default='n',
null=True,
blank=True,
max_length=5,
)
pweight = models.DecimalField(
null=True,
blank = True,
max_digits=10000,
decimal_places=2,
)
plimage = models.ImageField(
blank=True,
null=True,
)
Here is my forms.py
from django import forms
from .models import weightUnit
class RawProductForm(forms.Form):
name = forms.CharField(label="Name")
desc = forms.CharField(label="Beschreibung")
price = forms.DecimalField(label="Stückpreis")
sn = forms.CharField(label="Seriennummer")
weightunit = forms.ChoiceField(choices=weightUnit, label="Gewichteinheit")
weight = forms.DecimalField(label="Gewicht")
image = forms.ImageField(label="Bild")
Here is my views.py
def product_add(request):
pf = RawProductForm()
if request.method == "POST":
pf = RawProductForm(request.POST)
if pf.is_valid():
print(pf.cleaned_data)
Product.objects.create(**pf.cleaned_data)
else:
print(pf.errors)
context = {
"productform" : pf,
}
return render(request, "product_add.html", context)
You are working with a simple Form, not a ModelForm [Django-doc], so that means that it will not inspect the model at all. It will simply render a form. A ModelForm will inspect the model and construct a form based on that that you can customize.
class RawProductForm(forms.ModelForm):
class Meta:
model = Product
labels = {
'name': 'Name',
'desc': 'Beschreibung',
'price': 'Stückpreis',
'sn': 'Seriennummer',
'weightunit': 'Gewichteinheit',
'weight': 'Gewicht',
'image': 'Bild',
}
A ModelForm also has a .save(…) method [Django-doc] which creates a model object based on the data in the form and saves it to the database.

Image upload to the rich text field from vue to amazon s3 via django REST framework

I'm experimenting Vue with Django and creating a simple blog.
But I'm stuck about usage of uploading images vie CKEditor from vue.
uploading images to S3 is working within django-admin. But I couldn't figure out how can I serialize RichTextUploadField and make it work with vue.
My model is;
class Challenge(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
title = models.CharField(max_length = 240)
content = RichTextUploadingField(verbose_name='Code',null=True,blank=True)
slug = models.SlugField(max_length=255, unique=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="challenges")
image = models.ImageField(upload_to=upload_image_to, editable=True, null=True, blank=True)
def __str__(self):
return self.title
serializers.py;
author = serializers.StringRelatedField(read_only=True)
created_at = serializers.SerializerMethodField()
slug = serializers.SlugField(read_only=True)
moments_count = serializers.SerializerMethodField()
user_has_momented = serializers.SerializerMethodField()
class Meta:
model = Challenge
exclude = ["updated_at"]
def get_created_at(self, instance):
return instance.created_at.strftime("%B %d %Y")
def get_moments_count(self, instance):
return instance.moments.count()
def get_user_has_momented(self, instance):
request = self.context.get("request")
return instance.moments.filter(author=request.user).exists()
views.py
queryset = Challenge.objects.all().order_by("-created_at")
lookup_field = "slug"
serializer_class = ChallengeSerializer
permission_classes = [IsAuthenticated, IsAuthorOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
urls.py
router.register(r"challenges", cv.ChallengeViewSet)
urlpatterns = [
path("", include(router.urls)),
path("challenges/<slug:slug>/moments/", cv.ChallengeMomentListAPIView.as_view(), name="answer-list"),
path("challenges/<slug:slug>/moment/", cv.MomentCreateAPIView.as_view(), name="moment-create"),
path("moments/<int:pk>/", cv.MomentRUDAPIView.as_view(), name="moment-detail"),
path("moments/<int:pk>/like/", cv.MomentLikeAPIView.as_view(), name="moment-like"),
path('ckeditor/', include('ckeditor_uploader.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
frontend vue.js;
return this.loader.file
.then( uploadedFile => {
return new Promise( ( resolve, reject ) => {
const data = new FormData();
data.append( 'upload', uploadedFile );
axios( {
url: '/challenges/uploadsCK/',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data;'
},
withCredentials: false
} ).then( response => {
if ( response.data.result == 'success' ) {
resolve( {
default: response.data.url
} );
} else {
reject( response.data.message );
}
} ).catch( response => {
reject( 'Upload failed' );
} );
} );
} );
}
Everything is working as I expected. The only problem is imageupload via vue.js and I couldn't figure out how to configure it.
any help is appreciated.
after a very tiring trial - error session I found a solution by examining the django-admin behaviour. when I upload an image I get the path of upload endpoint and viola! just add the following path for ckfinder.
editorConfig: {
ckfinder: {
uploadUrl: "http://127.0.0.1:8000/ckeditor/upload/&responseType=json"
}
}
p.s: you can use relative path.

How to upload a file from django view using filepath

I have to upload a file from django views using the file path from the local system. I'm using models.create method to save the filepath. But the image is not getting uploaded into the media directory.
I have tried the Content and File from django core.utils but it deos not work
def createevent(request):
file_path = os.path.join(settings.FILES_DIR) # Getting the directory with files
f = []
for (dirpath, dirnames, filenames) in walk(file_path):
f.extend(filenames)
break
f.remove(".DS_Store")
img = random.choice(f) # Select a random file
pa = os.path.abspath(img) # absolute file path
# pa = (img,File(pa))
response = File(pa)
print(pa)
loc = "School Ground"
if request.method == 'POST':
get_dateof = request.POST.get('dateof')
get_nameof = request.POST.get('nameof')
get_descof = request.POST.get('descof')
new_report = Event.objects.create(
name=get_nameof,
description=get_descof,
location=loc,
timeoftheevent=get_dateof,
user=request.user,
image= pa
) #creating a db record
return HttpResponse('')
my models.py
class Event(models.Model):
name = models.CharField(max_length=100,blank=False)
description = models.CharField(max_length=100,blank=False)
location = models.CharField(max_length=100,blank=False)
timeoftheevent = models.CharField(max_length=100,blank=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
image = models.FileField(blank=False)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
You can try this.
#This would return a path for your saved images using path name/filename you can always tweak this
def user_directory_path(instance,filename):
return '{0}/{1}'.format(instance.name, filename)
class Event(models.Model):
name = models.CharField(max_length=100,blank=False)
description = models.CharField(max_length=100,blank=False)
location = models.CharField(max_length=100,blank=False)
timeoftheevent = models.CharField(max_length=100,blank=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
image = models.FileField(upload_to = user_directory_path, blank=False)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
then in your views.py and I'm assuming myfile is the name of the file field in your html form
if request.method == 'POST' and and request.FILES['myfile']:
get_dateof = request.POST.get('dateof')
get_nameof = request.POST.get('nameof')
get_descof = request.POST.get('descof')
myfile = request.FILES['myfile']
#creating a db record............
return HttpResponse('')
you can have a look at this article if it helps

How do i specify a file upload in django to a folder in reference to one of the model fields

I have the following django models in my Document app
class Section(models.Model):
choices = (
('Haematology', 'Haematology'),
('BloodBank', 'BloodBank'),
('Bacteriology', 'Bacteriology'),
('Parasitoloty', 'Parasitoloty'),
('Chemistry', 'Chemistry'),
('Histopathology', 'Histopathology'),
('Serology', 'Serology'),
('Immunology', 'Immunology'),
)
title = models.CharField(max_length = 50, choices = choices)
class Meta:
verbose_name = "Section"
verbose_name_plural = "Sections"
def __str__(self):
return str(self.title)
class Document(models.Model, instance):
documentSection = models.ForeignKey(Section)
category = models.ForeignKey(DocumentCategory)
title = models.CharField(max_length = 100, default = '')
description = models.TextField(null = True, blank = True, default = '')
documentFile = models.FileField(upload_to = 'uploads/' + instance.documentSection.title)
fileFormat = models.ForeignKey(FileFormat)
uploaded = models.DateField(auto_now_add=True, default=timezone.now)
modified = models.DateTimeField(auto_now=True, default=timezone.now)
uploaded_by = models.ForeignKey(User)
def __str__(self):
return str(self.title)
When i upload Documents i want then to be saved in a folder like 'uploads/documentSection/
or 'uploads/documentSection/%Y/%m/
My problem is i cant figure out how to take the value of the documentSection and parse it to upload_to = 'uploads/documentSection/

Django views.py code for parameter

I want to retrieve all image of a particular user. I need help.
here is my model
class image_archive(models.Model):
image_id = models.AutoField(primary_key=True)
event_id = models.ForeignKey(event_archive,db_column='event_id')
image_url = models.CharField(max_length=45)
screenshot_url = models.URLField(max_length=200)
image_title = models.CharField(max_length=45)
date_submitted = models.DateTimeField()
image_description = models.TextField()
original_image = models.ImageField(upload_to=file_upload_path)
formatted_image = ImageSpecField([FormatImage()],image_field='original_image', format='JPEG',
options={'quality': 90})
thumbnail_image = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1),
ResizeToFill(50, 50)], image_field='original_image',
format='JPEG', options={'quality': 90}
here is my urls.py
urlpatterns = patterns('gallery.views',
url(r'^(?P<event_id>\d+)/images/$', 'eventimage'),
)
here is my views.py
def eventimage(request,event_id):
e_piclist = image_archive.objects.get(id = event_id)
return render_to_response('gallery/image.html',
{
'e_piclist' : e_piclist,
'image_archive':image_archive,
})
But this doest not show the images of a particular event's image. Need help.
Your query is incorrect, you can query it using
e_piclist = image_archive.objects.filter(event_id = event_id).
Also, try to use .filter() instead of .get().
from django.shortcuts import render, get_object_or_404
def eventimage(request,event_id):
my_event = get_object_or_404(Event, pk=event_id)
image_list = my_event.image_archive_set.all()
return render(request,'gallery/image.html',{'e_piclist':image_list})