How to get an image from the server with django and graphql? - django

I already managed to make the mutations to upload, update and print the images. But how can I get the images files on in base64 in the query?
class Image(models.Model):
image = models.ImageField(blank=True, null=True, upload_to="uploads/images")
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)

I write my own solution.
First I created a new field in the ImageType object to store the image file in base 64. Additionally I validated that the value of the image field existed and the written address was associated with an existing file on the hard disk.
Then when the image is requested a new field called base64file appears with the stored image that can then be decoded in the frontend.
Hope this is helpful to someone. Here is my code:
class ImageType(DjangoObjectType):
class Meta:
model = Image
filter_fields = {'product_id': ['exact'],
interfaces = (relay.Node,)
base64file = graphene.String()
def resolve_base64file(self, info):
if self is not None and self.image and hasattr(self.image, 'url'):
if os.path.isfile(self.image.url):
return base64.b64encode(self.image.read())
else:
return 'File not found'
return ''

Related

How can I upload mutlple images at same time in Django?

I need upload multiple images in my form but I have just one imagefield, i don't want to have more imagefields the main idea is do a for each in the save method or something like that, but I don't have any idea to do that, please help.
This is my model:
class Archivos(models.Model):
id_archivo = models.AutoField(primary_key=True)
id_unidad = models.IntegerField()
nombre_archivo = models.CharField(max_length=255, blank=True)
imagen = models.ImageField(upload_to='img', null=True, blank=True)
I EDITED my def post
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('imagen')
if form.is_valid():
a = 0
for imagen in files:
a = a+1
img = form.save(commit=False)
img.id_unidad = 1
img.nombre_archivo ='hhh'+ str(a)
img.save()
print(a);
return self.form_valid(form)
else:
return self.form_invalid(form)
The for cicle works but always save the last image. I think it is working like and update but I don't understand why?
this is part of my form in a template:
the multiple imagefield
One of the choices is to create one more model for example ArchivosGallery with ForeignKey on your product. For example, if your product model called Archivos, then you should create:
class ArchivosGallery(models.Model):
image = models.ImageField(u'Images', upload_to='countries/images/', blank=True)
countries = models.ForeignKey('Archivos', blank=True, null=True)
to add images in product admin you have to add this code in admin.py:
class ImagesInline(admin.TabularInline):
model = ArchivosGallery
class ArchivosAdmin(admin.ModelAdmin):
inlines = [
ImagesInline,
]
admin.site.register(Archivos, ArchivosAdmin)
Hope its helps you
As #Zagorodniy suggested you probably want an extra table to keep the collection of uploaded images related to each other, using a ForeignKey in your image table. (if you need such a thing).
Anyway, to save multiple images, create instances of Archivos model in for loop and save it one by one:
files = request.FILES.getlist('imagen')
if form.is_valid():
for image in files:
instance = Planfile(
nombre_archivo = ... ,
id_unidad = ... ,
imagen = image
)
instance.save()
...
You should be able to access multipart values with getlist:
Here's an example:
for bfile in request.FILES.getlist('files'):
File(file=bfile, files=testing).save()

Django saving file to different model

I have a simple form which is used for submitting files which worked fine. I've since moved the file out from a field into its own table, now I'm really struggling as I need to add the file to the extra table and save the correct foreignkey in the form table. I've tried various snippets in save(), grabbing the file in the view and adding the file as an extra field but nothing is quite working.
The fairly obvious error is:
"Cannot assign InMemoryUploadedFile: Resource.file must be a File
instance"
class File(models.Model):
filename = models.CharField('Filename', max_length=200)
file = models.FileField()
mimetype = models.CharField('Mimetype', max_length=200)
pub_date = models.DateTimeField('date published', auto_now_add=True, blank=True)
def __str__(self):
return self.filename
class Resource(models.Model):
list_display = ('title', 'approved')
def __str__(self):
return str(self.title)
title = models.CharField('Title', max_length=200)
description = models.TextField('Description', null=True)
file = models.ForeignKey(File)
... cut for brevity
class ResourceForm(forms.ModelForm):
class Meta:
model = Resource
the problem is that you assign a file into a foreign key field. You need to instantiate the File object first and then set in to Resource object.
file = File(filename="test", file=temp_data, mimetype='pdf')
file.save()
resource.file = file
resource.save()

Use already uploaded image in Django's ImageField

Is there an option in ImageField to set the path or an already uploaded image?
My use case is as follows: I want to reutilize the same image in two different content entries. I don't want to upload the image twice or to store two copies of the same image.
Just assign the image field from one model instance to another:
original_entry = Entry.objects.get(pk=1)
another_entry = Entry.objects.get(pk=2)
another_entry.image = original_entry.image
another_entry.save()
new_entry = Entry.objects.create(image=original_entry.image)
Just put an image in it's own model:
class Image(models.Model):
image = models.ImageField(...)
class ModelA(models.Model)
image = models.ForeignKey(Image, null=True, blank=True)
class ModelB(models.Model)
image = models.ForeignKey(Image, null=True, blank=True)

Django 1.5 ModelForm like admin in view with images and foreign key

I have the following models:
class Quiver(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
is_default = models.BooleanField(default=False)
type = models.CharField(max_length=1, choices=QUIVER_TYPES)
category = models.CharField(max_length=255, choices=QUIVER_CATEGORIES)
def __unicode__(self):
return u'[%s] %s %s quiver' % (
self.user.username,
self.get_type_display(),
self.get_category_display())
class Image(models.Model):
photo = models.ImageField(upload_to=get_upload_file_path)
is_cover = models.BooleanField(default=False)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
def save(self, *args, **kwargs):
try:
this = Image.objects.get(pk=self.pk)
if this.photo != self.photo:
this.photo.delete(save=False)
except Image.DoesNotExist:
pass
super(Image, self).save(*args, **kwargs)
class Surfboard(models.Model):
quiver = models.ForeignKey(Quiver)
brand = models.CharField(max_length=255)
model = models.CharField(max_length=255)
length = models.CharField(max_length=255)
width = models.CharField(max_length=255, blank=True)
thickness = models.CharField(max_length=255, blank=True)
volume = models.CharField(max_length=255, blank=True)
images = generic.GenericRelation(Image)
def __unicode__(self):
return u'%s %s %s' % (self.length, self.brand, self.model)
def get_cover_image(self):
"Returns the cover image from the images uploaded or a default one"
for image in self.images.all():
if image.is_cover:
return image
return None
I'd like to be able to have the same form I have in the admin in my frontend view /surfboard/add:
As a new Django fan and user, I started to create the form from scratch. Not being able to do what I want with including the foreign key "quiver" as a dropdown list, I found in the doc the ModelForm, and decided to use it, so here what I got:
class SurfboardForm(ModelForm):
class Meta:
model = Surfboard
In my view, it looks like this and it's already a good start:
So now, I wanted to have a way to add pictures at the same time, and they are linked to a surfboard via a Generic Relation. Here I don't find the way to do a implementation like in the admin, and get frustrated. Any tips to do so?
Thanks!
What you seek is called an inline formset - see the docs for more.
It's also handy that you can render a formset quickly with {{ formset.as_p }}, but you'll need to write some JavaScript (or use the JavaScript that's used in the Django admin) to handle adding and removing forms.

Django ORM m2m limit to 1

# models.py
class Gallery(models.Model):
images = models.ManyToManyField(Image, null=True, blank=True)
class Image(models.Model):
image = models.ImageField()
# views.py
class GalleryIndex(ListView):
model = Gallery
I need to get thumbnail for every gallery, which is it's very first/last/whatever image.
How can I LIMIT image by 1 for any gallery as a custom attribute (to not override Gallery.images) without calling second SQL query?
A many-to-many acts as a descriptor for a normal queryset, so you can do my_gallery.images.all()[0] to limit the query to 1.
I don't think I understand correctly what you want to do, but doesn't below code work for you?
class Gallery(models.Model):
images = models.ManyToManyField(Image, null=True, blank=True)
def get_thumb(self):
return self.images.all()[0]
Or maybe other concept:
class Gallery(models.Model):
images = models.ManyToManyField(Image, null=True, blank=True)
thumbnail = models.ImageField()
def save(self, *args, **kwargs):
self.thumbnail = self.images.all()[0].image
(some exception catching here needed though)
I should've read docs better. Standard QuerySet API can't handle such cases efficiently (annotate() generates GROUP BY clause for each of parent fields which is slow) so I come with extra() method and raw subquery.
class GalleryIndex(ListView):
queryset = Gallery.objects.extra(select={'thumb':
"""
SELECT "image"
FROM "app_image", "app_gallery_images"
WHERE (
"app_gallery"."id" = "app_gallery_images"."gallery_id"
AND "app_gallery_images"."image_id" = "app_image"."id"
)
AND "app_image"."image" IS NOT NULL
LIMIT 1
"""
})
This queryset do exactly what I wanted, since SorlImageField (and ImageField) needs only filename to represent thumbnail in templates.