I am trying to get the image url from some model. I have made 2 models:
Restaurant model:
class Restaurant(models.Model):
from location.models import Area
from business.models import Business
name = models.CharField(verbose_name=_('Name'), max_length=255, unique=True)
address = models.CharField(verbose_name=_("Address"), max_length=255)
phone = models.CharField(verbose_name=_('Phone Number'), max_length=255)
email = models.EmailField(verbose_name=_('Email'), max_length=255, blank=True, null=True)
website = models.URLField(verbose_name=_('Website / Online Listing Link'), max_length=255, blank=True, null=True)
is_active = models.BooleanField(verbose_name=_("Is Active?"), default=True)
is_veg = models.BooleanField(verbose_name=_('Is Veg?'), default=True)
class Meta:
verbose_name = 'Restaurant'
verbose_name_plural = 'Restaurants'
And Restaurant Image model:
class RestaurantImage(models.Model):
image_type = models.CharField(verbose_name=_('Image Type'), choices=IMAGE_TYPES, max_length=255, default=RESTAURANT)
restaurant = models.ForeignKey(verbose_name=_('Restaurant'), on_delete=models.PROTECT, to=Restaurant)
image = models.ImageField(verbose_name=_('Select Image'), upload_to='media/')
def __str__(self):
return self.restaurant.name + " - " + IMAGE_TYPES_DICT[self.image_type]
class Meta:
verbose_name = 'Restaurant Image'
verbose_name_plural = 'Restaurant Images'
I need to get the image of the restaurant, so I tried to get the image by property method but got UnicodeDecodeError.
#property
def images(self):
images = []
for i in RestaurantImage.objects.filter(restaurant=self.id):
images.append(i.image)
return images
Please help me in getting the image url. Thank you.
So, I found a solution. It works as of now, but still, I would like to explore a better way of fetching an image.
#property
def images(self):
import sys
images = []
for i in RestaurantImage.objects.filter(restaurant=self.id):
file = 'http://' + sys.argv[-1] + '/'
image_path = i.image.file.name
file += image_path[image_path.find('images/'):]
images.append(file)
return images
I basically generated the path of the image.
Related
I am using django and I want to link two models. The first model is comment and the second model is image. I want to have multiple images for one comment and an image should be linked with only one comment.
Comment model has its fields and image model looks like this:
class Image(models.Model):
image = models.ImageField(upload_to=f'{hash(id)}/', null=True, blank=True)
def __str__(self):
return self.image.name
And this is the model that I used to link comment and image:
class CommentImage(models.Model):
comment = models.OneToOneField(Comment, models.CASCADE, null=True)
image = models.ForeignKey(Image, models.CASCADE, null=True)
class Meta:
ordering = ["-id"]
verbose_name = _("Image")
verbose_name_plural = _("Images")
def __str__(self):
return self.image.image.name
Here is the admin panel of django:
enter image description here
As you can see I could be able add only one image and there is no button as well to add multiple image. What should I change to be able to add multiple images?
I have tried using ManytoManyField and removing comment field from CommentImage but it did not work.
I think you are overcomplicating things. Why not just add a text field to your ImageComment:
class Image(models.Model):
def upload_to(self, filename):
return f'{hash(self)}/{filename}'
image = models.ImageField(upload_to=upload_to, null=True, blank=True)
comment = models.ForeignKey(
'ImageComment', on_delete=models.SET_NULL, null=True
)
def __str__(self):
return self.image.name
class CommentImage(models.Model):
comment = models.TextField()
Or in case an Image can have multiple ImageComments as well, use a ManyToManyField:
class Image(models.Model):
def upload_to(self, filename):
return f'{hash(self)}/{filename}'
image = models.ImageField(upload_to=upload_to, null=True, blank=True)
comments = models.ManyToManyField(
'ImageComment'
)
def __str__(self):
return self.image.name
class CommentImage(models.Model):
comment = models.TextField()
You can even add an InlineModelAdmin to make editing comments at the same location as the image possible:
from django.contrib import admin
class ImageCommentInline(admin.TabularInline):
model = ImageComment
#admin.site.register(Image)
class ImageAdmin(admin.ModelAdmin):
inlines = [
ImageCommentInline,
]
You can try using this via manytomanyfields:
class CommentImage(models.Model):
comment = models.ForeignKey(Comment, models.CASCADE)
image = models.ForeignKey(Image, models.CASCADE)
class Comment(models.Model):
# other fields here
images = models.ManyToManyField(Image, through='CommentImage', related_name='comments')
I have 3 django models. Requirement Model has its own fields. RequirementImage and RequirementDOc models have Requirement as foreign key in them which are used for multiple image and multiple document upload. In admin ,I want to show the Requirement along with the images and documents related to requirement. How can i show it in admin panel.
i want to show a view where i can list all fields of Requirement and RequirementImages and RequirementDocs together.
Below is the exact code of models.
class Requirement(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length = 5000)
mobile = models.CharField(max_length=15, null=True, blank=True)
email = models.EmailField(null=True, blank=True)
city = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class RequirementImage(models.Model):
requirement = models.ForeignKey('Requirement', on_delete=models.CASCADE)
image = models.ImageField(null=True, blank=True, validators=[
FileMimeValidator()
], upload_to=settings.MEDIA_RELATIVE_ROOT + "requirements/images")
class RequirementDoc(models.Model):
requirement = models.ForeignKey('Requirement', on_delete=models.CASCADE)
requirement_file = models.FileField(null=True, blank=True, upload_to=settings.MEDIA_RELATIVE_ROOT + "requirements/docs")
Python version is 3.7.12 and django version is 3.2.14
in models.py
from django.utils.safestring import mark_safe
class RequirementImage(models.Model):
requirement = models.ForeignKey('Requirement', on_delete=models.CASCADE)
image = models.ImageField(null=True, blank=True, validators=[
FileMimeValidator()
], upload_to=settings.MEDIA_RELATIVE_ROOT + "requirements/images")
def photo_tag(self):
return mark_safe('<img src="/your_path/{0}">'.format(self.image))
photo_tag.short_description = 'Photo of prescription'
photo_tag.allow_tags = True
and when you want to use it in admin
list_display = ('get_photo')
def get_photo(self, obj):
return obj.photo.photo_tag()
get_photo.short_description = 'Photo of prescription'
This is the right answer.we need to use TabularInline.
class RequirementImageInline(admin.TabularInline):
model = RequirementImage
fields = ['image']
extra = 1
class RequirementDocInline(admin.TabularInline):
model = RequirementDoc
fields = ['requirement_file']
extra = 1
class RequirementAdmin(admin.ModelAdmin):
inlines = [RequirementImageInline,RequirementDocInline]
Reference: https://stackoverflow.com/a/74233744/1388835
I have the following models:
class Camera(models.Model):
url = models.CharField(max_length=300, unique=True)
camera_number = models.IntegerField(null=False, blank=False,
validators=[
MaxValueValidator(1000),
MinValueValidator(1)])
camera_name = models.CharField(max_length=100, null=False, blank=False)
slug = models.SlugField(max_length=100, null=True, blank=False, unique=True)
class BaseImage(models.Model):
url = models.ForeignKey(Camera, on_delete=models.CASCADE)
base_image_filename = "base_images/" + str(Camera.slug) + "/%H"
image = models.ImageField(max_length=300, upload_to=base_image_filename)
What I am trying to do is to create the filename in BaseImage that contains the data in the slug variable of the corresponding Camera record. A camera can have many BaseImages but each BaseImage can only match to one Camera.
What I get in the name is something like "base_images/<django.db.models.query_utils.DeferredAttribute object at 0x7f6006bd9b70>/20/camera_1.jpg".
What do I need to change to get the slug field value as part of the filename ?
You can specify a method and pass a reference to that method:
from django.utils.timezone import now
class BaseImage(models.Model):
def get_image_filename(self, filename):
h = now().strftime('%H')
return f'base_images/{self.url.slug}/{h}/{filename}'
url = models.ForeignKey(Camera, on_delete=models.CASCADE)
image = models.ImageField(max_length=300, upload_to=get_image_filename)
i have two models ImageShoot and Image.
models.py:
class ImageShoot(models.Model):
name = models.CharField(max_length=100)
# image = models.URLField(name=None)
created_at = models.TimeField(auto_now_add=True)
def __str__(self):
return self.name
class Image(models.Model):
license_type = (
('Royalty-Free','Royalty-Free'),
('Rights-Managed','Rights-Managed')
)
image_number = models.CharField(default=random_image_number,max_length=12)
title = models.CharField(max_length = 100)
image = models.ImageField(upload_to = 'home/tboss/Desktop/image' , default = 'home/tboss/Desktop/image/logo.png')
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.CASCADE)
shoot = models.ForeignKey(ImageShoot, on_delete=models.CASCADE)
image_keyword = models.TextField(max_length=1000)
credit = models.CharField(max_length=150, null=True)
location = models.CharField(max_length=100, null=True)
license_type = models.CharField(max_length=20,choices=license_type, default='')
uploaded_at = models.TimeField(auto_now_add=True)
def __str__(self):
return self.title
admin.py:
class Imageset(admin.ModelAdmin):
associated_images = ImageShoot.image_set.all()
return associated_images
admin.site.register(Image)
admin.site.register(ImageShoot,Imageset)
what i am trying to achieve that when i create a image it should show on imageshoot also like when i create image in shoot 1. this image should show on shoot 1.
i am not sure which field should i add on imageshoot.
Use Reverse lookup
In Your views you can get all the images associated with the ImageShoot Obj using set.Try this in your shell after briefly going through the docs
associated_images = ImageShoot.image_set.all()
You can also use django orm methods for querysets like filter, count, etc.
Edit:
To display related images you can use this in admin:
#admin.register(ImageShoot)
class Imageset(admin.ModelAdmin):
list_display = ('name', 'created_at', 'associated_images')
def associated_images(self, obj):
return obj.image_set.all() #<----edit
associated_images.admin_order_field = 'imageshoot_image'
First time posting, having a bit of a weird issue with Django's Admin TabularInline. Couldn't seem to find the problem in any searches.
When I add a value - in this case a Financial Quote - and save the entry, the page will refresh having added the instance and an additional 2 entries that have empty values in every field.
The same happens if I flag them for deletion from the admin page. It deletes all entries and then adds 3 more in the place of the previous ones.
The same happens with the Invoice model (which is a similar model) but not with the Purchase models which behaves as expected. This leads me to think i've done something odd when I've written the models.
Image attached to show the result.
Hopefully someone can see where i've gone wrong
Thanks!
models.py
class Quote(models.Model):
job = models.ForeignKey(Job, related_name="quotes", on_delete=models.CASCADE)
number = models.AutoField(primary_key=True)
currency = models.ForeignKey(Currency, blank=True, null=True)
amount = models.DecimalField(max_digits=20, decimal_places=2, default="0.00", verbose_name="Amount Invoiced")
created = models.DateTimeField(auto_now=False, auto_now_add=True)
created_by = models.ForeignKey(Profile, related_name='quoted', blank=True, null=True, on_delete=models.SET_NULL)
sent = models.BooleanField(default=False)
superceded = models.BooleanField(default=False)
tax = models.DecimalField(max_digits=20,decimal_places=2,default=20.00, verbose_name="Tax Rate")
def __unicode__(self):
return self.created.strftime("%B %d, %Y") + " | " + u'%s' % (self.currency) + str(self.amount)
def readable_date(self):
return self.created.strftime("%B %d, %Y")
class Invoice(models.Model):
job = models.ForeignKey(Job, related_name="invoices", blank=True, null=True, on_delete=models.SET_NULL)
number = models.AutoField(primary_key=True)
currency = models.ForeignKey(Currency, blank=True, null=True)
amount = models.DecimalField(max_digits=20, decimal_places=2, default="0.00", verbose_name="Amount Invoiced")
created = models.DateTimeField(auto_now=False, auto_now_add=True)
created_by = models.ForeignKey('profiles.Profile', related_name='invoiced', blank=True, null=True, on_delete=models.SET_NULL)
paid = models.BooleanField(default=False)
sent = models.BooleanField(default=False)
superceded = models.BooleanField(default=False)
tax = models.DecimalField(max_digits=20,decimal_places=2,default=20.00, verbose_name="Tax Rate")
def __unicode__(self):
return self.created.strftime("%B %d, %Y") + " | " + u'%s' % (self.currency) + str(self.amount)
def readable_date(self):
return self.created.strftime("%B %d, %Y")
def get_day(self):
return self.created.strftime("%d")
def get_month(self):
return self.created.strftime("%b")
admin.py
from finance.models import Purchase, Quote, Invoice
from django.contrib import admin
from .models import Job
class QuoteInline(admin.TabularInline):
model = Quote
class InvoiceInline(admin.TabularInline):
model = Invoice
class PurchaseInline(admin.TabularInline):
model = Purchase
class JobModelAdmin(admin.ModelAdmin):
list_display = [
'job_number',
'brand',
'job_name',
'client',
'account_manager',
'last_updated_by',
'updated',
'status',
]
list_display_links = ['job_name']
list_filter = ['client']
inlines = [
QuoteInline,
PurchaseInline,
InvoiceInline
]
Example of issue in admin page
In your inline classes set extra=0. I guess you have this problem because you have fields with default values and no any required fields in auto-created instances, so you accidentially save them, and django didn't raise any errors.