Alternative to Django's image.url method? - python

I'm using an inlineformset so that a user can upload multiple images at once. The images are saved and functionality is as expected, except on the front-end side. When I loop through my formset with a method resembling {{ form. image }}, I can clearly see that my image is saved and when I click the url, I am redirected to the uploaded file. The problem seems to be that the absoulte url is not stored when I try to set the image's URL as a src for an image element.
Trying to log MEDIA_URL and MEDIA_ROOT in a <p> tag yields no results.
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
ROOT_URLCONF = 'dashboard_app.urls'
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
urls.py
from django.conf.urls import url, include
from . import views
from django.conf.urls.static import static
from django.conf import settings
app_name = 'Accounts_Namespace'
urlpatterns = [
url(r'^$', views.Register, name='Accounts_Register'),
url(r'^change-password/$', views.ChangePassword, name="Accounts_Change_Password"),
url(r'^login/$', views.Login, name='Accounts_Login'),
url(r'^logout/$', views.Logout, name='Accounts_Logout'),
url(r'^profile/$', views.ViewProfile, name='Accounts_View_Profile'),
url(r'^profile/edit/$', views.EditProfile, name="Accounts_Edit_Profile"),
url(r'^school/', include('student_map_app.urls', namespace="Student_Maps_Namespace")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
models.py
class Gallery(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
image = models.ImageField(upload_to="gallery_images")
uploaded = models.DateTimeField(auto_now_add=True)
views.py
def EditProfile(request):
user = request.user
galleryInlineFormSet = inlineformset_factory(get_user_model(), Gallery, form=GalleryForm)
selectedUserGallery = Gallery.objects.filter(user=user).order_by('uploaded')
userGallery_initial = [{'image': selection.image} for selection in selectedUserGallery] # Using this syntax because formset initials accept dictionaries
if request.method == "POST":
profile_form = ProfileEditForm(request.POST, instance=request.user)
gallery_inlineformset = galleryInlineFormSet(request.POST, request.FILES) # Essentially, we're passing a queryset
if profile_form.is_valid() and gallery_inlineformset.is_valid():
# Altering the User model through the UserProfile model's UserProfileForm representative
user.first_name = profile_form.cleaned_data['first_name']
user.last_name = profile_form.cleaned_data['last_name']
user.save()
new_images = []
for gallery_form in gallery_inlineformset:
image = gallery_form.cleaned_data.get('image')
if image:
new_images.append(Gallery(user=user, image=image))
try:
Gallery.objects.filter(user=user).delete()
Gallery.objects.bulk_create(new_images)
messages.success(request, 'You have updated your profile.')
except IntegrityError:
messages.error(request, 'There was an error saving your profile.')
return HttpResponseRedirect('https://www.youtube.com')
else:
profile_form = ProfileEditForm(request.user)
gallery_inlineformset = galleryInlineFormSet(initial=userGallery_initial)
args = { 'profile_form':profile_form, 'gallery_inlineformset':gallery_inlineformset }
return render(request, 'accounts_app/editprofile.html', args)
editprofile.html
{% block main %}
<section class="Container">
<section class="Main-Content">
<form id="post_form" method="POST" action='' enctype='multipart/form-data'>
{% csrf_token %}
{{ gallery_inlineformset.management_form }}
{% for gallery_form in gallery_inlineformset %}
<div class="link-formset">
{{ gallery_form.image }} <!-- Show the image upload field -->
<p>{{ MEDIA_ROOT }}</p>
<p>{{ MEDIA_URL }}</p>
<img src="/media/{{gallery_form.image.image.url}}">
</div>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
</form>
</section>
</section>
{% endblock %}
Again, when I try:
<img src="{{ MEDIA_URL }}{{ gallery_form.image.url }}">
I get a value of "unknown" as the source, but I can click the link that "{{ gallery_form.image}}" generates and see the image that was uploaded. Trying to log both "MEDIA_URL" and "MEDIA_ROOT" yields no results. Not quite sure where the issue lies.

Use <img src="{{ gallery_form.image.url }}"> and make sure image is not None
add this line in your urls.py
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

No need to add {{MEDIA_URL}} before address of your image. because by default it will add /media before your image url path.
Also be sure to add all path starting media to your urls.
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT}))
also when trying to print an image url in django template, handle situations that image not exist like this:
<img src="{% if gallery_form.image %}{{ gallery_form.image.url }}{%else%} <default-image-path-here> {%endif%}"

While I didn't figure out why I couldn't use the .url() method Django has predefined, I did however, end up using another solution suggested to me by a user in a previous question of mine. Basically, after a user has uploaded images and we have them stored in a database, we make a variable storing the URL attribute of those images, and access that variable from the template. It looks something like this:
views.py
selectedUserGallery = Gallery.objects.filter(user=user) # Get gallery objects where user is request.user
userGallery_initial = [{'image': selection.image, 'image_url':selection.image.url} for selection in selectedUserGallery if selection.image]
if request.method == "GET":
print("--------GET REQUEST: PRESENTING PRE-EXISTING GALLERY IMAGES.-------")
profile_form = ProfileEditForm(request.user)
gallery_inlineformset = galleryInlineFormSet(initial=userGallery_initial)
template.html
<form id="post_form" method="POST" action='' enctype='multipart/form-data'>
{% csrf_token %}
{{ gallery_inlineformset.management_form }}
{% for gallery_form in gallery_inlineformset %}
<div class="link-formset">
{{ gallery_form.image }} <!-- Show the image upload field, this is not he image var from views.py -->
{% if gallery_form.image is not None %}
<p>The image should be below:</p>
<img src="{{ gallery_form.initial.image_url }}">
{% endif %}
</div>
{% endfor %}
<input type="submit" name="gallery-submit" value="Submit" />
</form>
Also, I ended up replacing most of code from the original post as I'm no longer using bulk_create().

Related

Django - i always get my profile when i what to view another users profile

Whenever i tried to view other people profile, it always return my own profile again, i don't really know what's wrong and i have tried calling request.user but it seems not to work
views.py
def UserProfile(request, username):
user = get_object_or_404(User, username=username)
profile = Profile.objects.get(user=user)
url_name = resolve(request.path).url_name
context = {
'profile':profile,
'url_name':url_name,
}
return render(request, 'userauths/profile.html', context)
urls.py main project
from userauths.views import UserProfile
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('userauths.urls')),
path('<username>/', UserProfile, name='profile'),
]
index.html
{% for creator in creators %}
<img class="avatar-img rounded-circle" src="{{creator.user.profile.image.url}}" alt="creators image" ></div>
<h5 class="card-title"><a href="{% url 'profile' creator.user %}">
{{creator.user.profile.first_name}} {{creator.user.profile.last_name}} {% if creator.verified %} <i class="bi bi-patch-check-fill text-info smsall" ></i> {% else %}{% endif %} </a></h5>
<p class="mb-2">{{creator.user.profile.bio}}</p></div>
{% endfor %}
I just fixed it now, in my profile.html, i am using {{request.user.profile.first_name}} to display the informations. I was supposed to use {{profile.first_name}} etc, and that was it.
Instead of this:
<a href="{% url 'profile' creator.user %}">
you should try:
<a href="{% url 'profile' creator.user.username %}">
From the presumably working statement get_object_or_404(User, username=username) I assume that username is a field (hopefully, unique) of the User. So you should pass it onto the URL, not the entire User model.

Displaying an image from a model in a Django template

I'm trying to access an image from a model in my template:
In my template, I have:
{% for server in servers %}
<div class="hs-item set-bg" data-setbg="{{ server.image.url }}">
<div class="hs-text">
<div class="container">
<h2>The Best <span>Games</span> Out There</h2>
<p>Lorem ipsum.</p>
Read More
</div>
</div>
</div>
{% endfor %}
And my models look like this:
class Server(models.Model):
Name = models.CharField(max_length=100)
IP = models.CharField(max_length=50)
Port = models.IntegerField()
Image = models.ImageField(default='default.jpg', upload_to='server_pics')
def __str__(self):
return str(self.Name) if self.Name else ''
I've added this to my settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
And this to my urls.py:
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
But it doesn't display the image, and I don't get an error in the console... Not sure what I'm doing wrong here...
However, when I replace {{ server.image.url }} in my template by a static image, it works.
I found the solution, I had to change server.image.url to server.Image.url, which fixed the issue.

How can I get the url of a Django ImageField?

I am using a modelformset_factory method with forms containing only an ImageField. The Model the forms are based on contains a user field that has a many-to-one relationship with a User Model that extends AbstractUser(See Extending User Model with Abstract User). Currently, each instance of a user has a correlating User Profile, but I would also like to allow the user to upload a gallery of images to their profile.
models.py
class Gallery(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
image = models.ImageField(upload_to='user_gallery', blank=True, null=True)
def create_gallery(sender, **kwargs):
if kwargs['created']:
user_gallery = Gallery.objects.create(user=kwargs['instance'])
user_gallery.save();
post_save.connect(create_gallery, sender=User)
forms.py
class GalleryForm(forms.ModelForm):
image = forms.ImageField(label='FormImage')
class Meta:
model = Gallery
fields = ['image']
views.py
def EditProfile(request):
GalleryFormSet = modelformset_factory(Gallery, form=GalleryForm, extra=3, max_num=3)
if request.method == "POST":
formset = GalleryFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.cleaned_data:
my_image = form['image']
photo = Gallery(user=request.user, image=my_image)
photo.save()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
else:
formset = GalleryFormSet()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
Template
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{form.image}}
<img src="{{form.image.url}}"/>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
</form>
The problem I'm have is that using {{ form.image }} produces this result:
... and using {{ form.image.url }} within an image's source tag produces absolute nothing at all. When I inspect the element I contain it in, it states the source is unknown. Obviously, the images are being saved in the DB as I'd like, but I can't get the .url functionality to work. And YES, I do have the media root an all defined:
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'HighlightPage_Project/media')
urls.py
urlpatterns = [
url(r'^$', views.Login_Redirect),
url(r'^account/', include('user_handler_app.urls')),
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Try to replace your code with the following code:
<img src="{{form.image.url}}"/>
with:
<img src="{{form.instance.image.url}}"/>
Try to replace your code with the following code:
views.py
def EditProfile(request):
GalleryFormSet = modelformset_factory(Gallery, form=GalleryForm, extra=3, max_num=3)
if request.method == "POST":
formset = GalleryFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.cleaned_data:
my_image = form['image']
photo = Gallery(user=request.user, image=my_image)
photo.save()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
else:
user_images = Gallery.objects.filter(user=request.user)
initial_images = [{'image': i.image, 'image_url': i.image.url} for i in user_images if i.image]
formset = GalleryFormSet(initial=initial_images)
return render(request, 'user_handler/editprofile.html', {'formset': formset})
Template
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{form.image}}
<img src="{{form.initial.image_url}}"/>
{% endfor %}
<input type="submit" name="submit" value="Submit" />

django ImageField not displaying, throws ImportError

I have a model where I have an image name, image description, and an image. I want to use these fields to display a div with the image description and name with the thumbnail for each row in my model. Right now when I am trying to render the template I am getting:
TypeError: 'ImageFieldFile object is not subscriptable
During handling of the above exception another error occured:
ImportError: No module named 'backends'
Code:
Models.py
class PictureType(models.Model):
name = models.CharField(max_length = 150)
description = models.CharField(max_length = 1000)
image = models.ImageField(upload_to='AppName/images/')
views.py
class indexView(generic.ListView):
model = PictureType
template_name = 'index.html'
index.html
{% for visual in object_list %}
<div class="col-sm-4">
<div class="thumbnail">
<a href="#" class="">
<div align="center" class={{ visual.name }}>
<h4 class="">{{ visual.name }}</h4>
<p class="">{{ visual.description }}
</p>
</div>
<img src= "{{ visual.image.url }}" alt="..." class="">
</a>
</div>
</div>
{% endfor %}
settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'media')
MEDIA_URL = '/media/'
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', indexView.as_view(), name = 'index'),
]
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
UPDATE:
When I change:
<img src= "{{ visual.image.url }}" alt="..." class="">
to
<img src= "{{ visual.image }}" alt="..." class="">
I don't get the above errors but the images don't come through either, they look like this:
Sounds like you are trying to import 'backends' module somewhere in your code, but it does not exist in the python path.
Hope this was helpful.
You have to tecth the Image URL from DataBase and Pass it to your HTML template file as context data type.
first you have to make sure that, you have been installed Pillow Library
(pip instal pillow)
And load static files to index.html file
{% load static %} - use this code on the begining of HTML
then change your view.py Function to :
class indexView(generic.ListView):
model = PictureType
users = PictureType.objects.all()
args = {'users':users}
template_name = 'index.html',args
or better way to Pass the data is change your Views as Function.
def indexView(request):
model = PictureType
users = PictureType.objects.all()
args = {'users':users}
return render(request,"index.html", args)

Django image (media) path don't display correctly in template

In my project i had set my media folder like this:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
urlpatterns = [
....
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
then in my models.py i create a class like this one:
class PD_Pictures(models.Model):
pic_IDmod = models.ForeignKey(PD_Models, related_name='modello')
pic_image = models.ImageField()
pic_descr = models.CharField(max_length=50)
def __str__(self):
return self.pic_descr
at this point in my function in views.py I extract all values in db related to PD_Picture:
prod_img = PD_Pictures.objects.all()
.....
return render(
request,
'base_catalog.html',
{
'bike_mod': bike_models,
'prod_img': prod_img,
'cat_list': cat_list,
'menu_list': menu_list['menu'],
'pcontent': menu_list['cont'],
'form': c_form
},
context
)
and in my template, i would ti display related images:
{% for pic in prod_img %}
<div class="4u">
<span class="image fit"
<img src="{{ pic.pic_image }}" alt="" />
</span>
</div>
{% endfor %}
Well, at this point when I insert a new image in db, in table the path is newimage.jpg, physically on my server the image was stored in /media/newimage.jpg, how can I extract the value from the table and concatenate to the media path in my template? (<server>/media/newimage.jpg)
I have tried to use upload_to='/models/' in my ImageField but the only effect is to save image into another model folder into main model.
just try like this
{% for pic in prod_img %}
<img src="{{ pic.pic_image.url }}" alt="" />
{% endfor %}
From django official doc:
FieldFile.url
A read-only property to access the file’s relative URL by calling the url() method of the underlying Storage class.
if you try to print in your template {{ pic.pic_image }} you'll receive the db field value, while with {{ pic.pic_image.url }} the url() method from django.core.files.storage.Storage will call, and your base settings
would seem to be correct
Can you make this into your template and see what path is given?
{% for pic in prod_img %}
<p>{{ pic.pic_image }</p>
{% endfor %}

Categories