I am trying to update Profile photo with Django
According to yt tutorials I created form for updating photo:
class UserProfileForm(forms.ModelForm):
class Meta:
model = User_Model
fields = ["profile_photo"]
And this is my class to Change photo in views:
class UpdatePhoto(TemplateView):
template_name = "Messenger/update_photo.html"
profile_form = UserProfileForm
def post(self, response):
data = response.POST
file_data = response.FILES
profile_form = UserProfileForm(data, file_data, instance=response.user.profile)
if profile_form.is_valid():
profile_form.save()
return redirect("/")
print("rere")
context = self.get_context_data(profile_form=profile_form)
return self.render_to_response(context)
My Model:
class User_Model(models.Model):
user = models.OneToOneField(
User, null=True, on_delete=models.CASCADE, related_name="profile"
)
profile_photo = models.ImageField(
upload_to="images/", default="default_photo.jpg", null=True, blank=True
)
chats = models.ManyToManyField(User, related_name="chats", blank=True)
blocked_list = models.ManyToManyField(User, related_name="blocked_list", blank=True)
I was trying with and without 'response.POST', result was the same, it does not update. However when I try to print 'file_data' I get something like this:
<MultiValueDict: {'Browser': [<InMemoryUploadedFile: thumb.jpg (image/jpeg)>]}>
Main Settings.py:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = "static/"
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
And main urls.py:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("Messenger.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
App urls:
from django.urls import path
from django.contrib.auth.decorators import login_required
from . import views
urlpatterns = [
path(
"",
login_required(views.Chat_list_Usernames.as_view(), login_url="/login"),
name="home",
),
path(
"change_status/",
login_required(views.change_status, login_url="/login"),
name="change_status",
),
path("login/", views.login_page, name="login_page"),
path(
"logout/", login_required(views.logout_user, login_url="/login"), name="logout"
),
path("register/", views.register_page, name="register_page"),
path(
"update_photo/",
login_required(views.UpdatePhoto.as_view(), login_url="/login"),
name="update_photo",
),
path(
"change_password/",
login_required(views.ChangePassword.as_view(), login_url="/login"),
name="change_password",
),
path(
"send_message/",
login_required(views.SendMessage.as_view(), login_url="/login"),
name="send_message",
),
]
And my template:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/update_photo.css'%}">
<div class="main-content">
<div class="heading">Change</div>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="photo">
<div class="button">
<input id="files" required type="file" name="Browser"
accept="image/png, image/jpeg, image/jpg, image/webp">
</div>
<div class="buttons">
<div class="button">
<input type="button" name="Back" , value="Back">
</div>
<div class="button">
<input type="submit" name="Change" , value="Change">
</div>
</div>
</form>
</div>
Also I need to mention that I can update photo though admin panel but it's how this should work .
I Have no idea what have I done wrong and how to make it work right.
You should use UpdateView instead of TemplateView as it only renders a given template, with the context containing parameters captured in the URL.
Related
my image file is not loading in webpage it is showing The 'Img' attribute has no file associated with it
models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=100,unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
updated_on = models.DateTimeField(auto_now= True)
content = models.TextField()
created_on = models.DateTimeField(default=timezone.now())
status = models.IntegerField(choices=STATUS, default=0)
Img = models.ImageField(null =True, blank = True, upload_to='static/images')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
urls.py
from django.contrib import admin
from django.conf.urls import include
from django.urls import path
from portfo import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.firstpage,name='firstpage'),
path('', include('portfo.urls')),
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,"static")
]
MEDIA_URL ="/images/"
MEDIA_ROOT=os.path.join(BASE_DIR,'static/images')
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
template
{% for post in posts %}
<div class="card mb-4">
<div class="card-body " style="background-color: #F2F4F3;">
<img src="{{post.Img.url}}" />
<h2 class="card-title" style="margin-left:40% ;">{{ post.title|capfirst }}</h2>
<p class="card-text text-muted h6">{{ post.author }} | {{ post.created_on}} </p>
<p class="card-text">{{post.content|slice:":200" }}...</p>
Read More
</div>
</div>
{% endfor %}
I have a file name images inside the static. Your help is much appriciated
I want to let the user upload multiple images per post. Similarly to an e-commerce platform with multiple images per product. But till now the images are not sent to the database.
That's my code so far:
models.py:
class Project(models.Model):
title = models.CharField(max_length=200)
describtion = models.TextField(null=True, blank=True)
class ProjectImage(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
image = models.FileField(upload_to="products")
forms.py:
class ProjectForm(ModelForm):
image = forms.ImageField(widget=ClearableFileInput(attrs={'multiple':True}))
class Meta:
model = Project
fields = ['title', 'describtion']
views.py:
def createProject(request):
form = ProjectForm()
if request.method == 'POST':
form = ProjectForm(request.POST)
images = request.FILES.getlist('image')
if form.is_valid():
project = form.save()
for i in images:
ProjectImage(project=project, image=i).save()
context = {'form':form}
return render(request, 'projects/project_form.html', context)
project_form.html:
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form__field">
<label for="formInput#text">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<input type="submit" name="" id="">
</form>
settings.py:
STATIC_URL = '/static/'
MEDIA_URL = '/images/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/images')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
project urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('projects.urls')),
]
app urls.py
urlpatterns = [
path("", views.createProject, name="create-project")
]
Issue:
You have made ProjectForm which relates to Project model, but the image field is in ProjectImage model. So, image field is not even passing to the template and you also haven't passed it in fields=['title','describtion'] in ProjectFrom.
You haven't made configurations for saving the media files in project's urls.py.
Solution:
You should make two forms in forms.py, first ProjectForm which will get the data for Project model and second ProjectImageForm which will get the list of images, then using request.FILES.getlist('image') you can save images which relates to a particular instance one by one in loop as you tried to save.
You should make media configurations in project's urls.py
Try Below Code:
forms.py
from django import forms
from django.forms import ClearableFileInput
from .models import Project, ProjectImage
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['title', 'describtion']
class ProjectImageForm(forms.ModelForm):
class Meta:
model = ProjectImage
fields = ['image']
widgets = {
'image': ClearableFileInput(attrs={'multiple': True}),
}
views.py
from django.http import HttpResponse
from django.shortcuts import redirect, render
from .forms import ProjectImageForm, ProjectForm
from .models import Project, ProjectImage
def createProject(request):
form = ProjectForm()
form2 = ProjectImageForm()
if request.method == 'POST':
form = ProjectForm(request.POST)
form2 = ProjectImageForm(request.POST, request.FILES)
images = request.FILES.getlist('image')
if form.is_valid() and form2.is_valid():
title = form.cleaned_data['title']
describ = form.cleaned_data['describtion']
print(title, describ)
project_instance = Project.objects.create(
title=title, describtion=describ)
print('-------------------------------------------')
print(project_instance)
print('-------------------------------------------')
for i in images:
ProjectImage.objects.create(project=project_instance, image=i)
return redirect('thanks')
context = {'form': form, 'form2': form2}
return render(request, 'projects/project_form.html', context)
def thanks(request):
return HttpResponse('<h1>Form saved.</h1>')
project_form.html or template file:
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.title.label_tag}}
{{form.title}}
<br><br>
{{form.describtion.label_tag}}
{{form.describtion}}
<br><br>
{{form2.image.label_tag}}
{{form2.image}}
<br><br>
<input type="submit" name="" id="">
</form>
project's urls.py
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('projects.urls'))
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
app's urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home.urls'))
]
Your models.py and settings.py can be remain same, but it's recommended to use
MEDIA_URL = 'media/' and MEDIA_ROOT = os.path.join(BASE_DIR, 'media/'), then you should make nested folders inside it to save images or any files.
Note: You should always return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good practice in general as stated in the tutorial4.
Note: Function based views are generally written in snake_case not camelCase, you may change it to create_project from createProject.
Note: Add / at the end of upload_to as upload_to='products/' in FileField in ProjectImage model.
I'm building a photo blog via Django, it has a very basic structure:
1)a list page: each post has a cover picture
2)severals detail pages correspondant: each page contains multiple pictures.
At the list page, things are all good, the cover picture displayed correctely, but for the detail web page, the pictures that I uploaded from django admin won't show up, though they can be found in the local folder \media. I checked the page in Chrome, I got this: <img src(unknown) alt>. I'm confused.
Thanks a lot for your time and help.
structure :
lyv_dev #project name
--settings.py
--urls.py
media
--upload1.jpg
--upload2.jpg
--upload3.jpg
-- ...
project #app name
-- templates
--projects
-- base.html
-- list.html
-- detail.html
-- urls.py
-- admin.py
-- views.py
static
-- css
-- style.css
db.sqlite3
manage.py
models.py
from django.db import models
from django.urls import reverse
# models project
class Project(models.Model):
title = models.CharField(max_length = 250)
slug = models.SlugField(max_length = 250, unique_for_date = 'publish')
text = models.TextField()
year = models.IntegerField(default = 2020)
# couv: this is a cover picture
couv = models.FileField(blank=True)
height = models.IntegerField(default=0)
weidth = models.IntegerField(default=0)
class Meta:
ordering = ('-publish', )
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('projects:project_detail', args=[self.slug])
# Images related with project
class ProjectImage(models.Model):
project = models.ForeignKey(Project, on_delete = models.CASCADE, related_name='projectimages')
images = models.FileField()
def __str__(self):
return self.project.title
admin.py
from django.contrib import admin
from .models import Project, ProjectImage
class ProjectImageAdmin(admin.TabularInline):
model = ProjectImage
#admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'publish', 'status')
list_filter = ('status', 'publish')
search_fields = ('title', 'text')
prepopulated_fields = {'slug':('title',)}
date_hierarchy = 'publish'
ordering = ('status', 'publish')
inlines = [ProjectImageAdmin]
class Meta:
model = Project
#admin.register(ProjectImage)
class PostImageAdmin(admin.ModelAdmin):
pass
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [str(BASE_DIR.joinpath('static'))]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
urls.py (in django project folder)
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('projects.urls', namespace='projects')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
urls.py (in django app folder)
from django.urls import path
from .import views
from .views import ProjectLisView
app_name = 'projects'
urlpatterns = [
path('', ProjectLisView.as_view(), name='projects_list'),
path('projects/<slug:project>/', views.project_detail, name='project_detail'),
]
views.py
from django.shortcuts import render, get_object_or_404
from .models import Project, ProjectImage
from django.views.generic import ListView
class ProjectLisView(ListView):
model = Project
template_name = 'projects/list.html'
context_object_name = 'projects'
def project_detail(request, project):
project = get_object_or_404(Project, slug=project, status='published')
images = project.projectimages.all()
return render(request, 'projects/detail.html', {'project':project, 'images':images})
list.html
{% extends "projects/base.html" %}
{% block content %}
{% for project in projects %}
<p class="title">{{project.title}}</p>
<div><img src="{{ project.couv.url }}" alt=""></div>
{% endfor %}
{% endblock %}
detail.html
{% extends "projects/base.html" %}
{% block content %}
<p>this is a detail page</p>
{{ project.title }}
{{ project.year }}
<p>{{ project.width }} x {{ project.height }} mm </p>
{% for image in images %}
<div><img src="{{ images.url }}" alt=""></div>
{% endfor %}
{% endblock %}
base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<section class="content">
{% block content %}
{% endblock %}
</section>
</body>
</html>
Does not display an image!
image is exists, dut django didn't display any images on page, how to fix this?
this is my models.py
class All_Images_Of_The_Series(models.Model):
to_series = models.ForeignKey(Series, on_delete=models.CASCADE, blank=True, default=None)
image_of_all = models.ImageField(upload_to="previews/previews_for_series/", default=None,width_field="width_field", height_field="height_field")
is_poster = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
width_field = models.IntegerField(default=0)
height_field = models.IntegerField(default=0)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return "Active: |%s| and Poster: |%s| " % (self.is_active, self.is_poster)
class Meta:
ordering = ["-timestamp"]
verbose_name = 'All_Images_of_the_Series'
verbose_name_plural = 'All_Images_of_the_Series'
this is my views.py
def homeview(request, *args, **kwargs):
full_path = All_Images_Of_The_Series.objects.all()
context = {"full_path":full_path,}
return render(request, 'home.html', context)
this is my template
<div class="col-sm-3 right-side">
<div class="new-movies-block">
<a class="header" href="#/new/">
<div class="title">Новинки</div>
</a>
{% for one_to_one_path in full_path %}
<div class="movie-spacer" ></div>
<a class="new-movie" href="{{ one_to_one_path.to_series.get_absolute_url }}" title="{{ one_to_one_path.to_series.eng_name }}">
<div class="title-info">
{{ one_to_one_path.to_series.season_of_this_series.number_of_season }} сезон {{ one_to_one_path.to_series.number_of_series }} серия
</div>
<div class="date">{{ one_to_one_path.to_series.timestamp_rus }}</div>
<img src="{{ one_to_one_path.image_of_all.url }}" class="img-responsive">
</a>
{% endfor %}
</div>
</div>
If you look at the element code, the images, then in the line "src" there is a path to the picture, and it's working! But does not display the picture itself!
<img src="/media/previews/previews_for_series/1.png" class="img-responsive">
this is error in console(f12)
GET http://127.0.0.1:8000/media/previews/previews_for_series/1.png 404 (Not Found)
Do this !
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^series/', include("serials.urls", namespace='series')),
url(r'^', include("serials.urls", namespace='homeview')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
just a quick thoughts, you don't show me the things you might need to work. For example if this if for development on the urls you need this https://docs.djangoproject.com/en/1.11/howto/static-files/#serving-files-uploaded-by-a-user-during-development and on your settings you may need something like that
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
I hope it helps
Best
Perhaps you haven't added the media to your urls.py
From django.conf import settings
# your stuff
if settings.DEBUG:
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT
})
)
I have images I uploaded through django admin, but they are not displaying. The weird thing is that I have another project with the EXACT same code and it works. object.image.url outputs /media/media/image.jpg as does my other project. But this project does not show the image. if I put an image from my static folder or if I hardcode an image, it works fine. The problem is only when I try an image uploaded from the admin it does not work. Am I missing something in my settings.py file? or anywhere?
Models.py:
from django.db import models
# Create your models here.
class Connect(models.Model):
title = models.CharField(max_length=70)
short_description = models.TextField(null=True, blank=True)
description = models.TextField()
image = models.ImageField(upload_to='media', blank=True, null=True)
def __str__(self):
return self.title
views.py:
def index(request):
about = About.objects.all()
staff = Staffmembers.objects.all()
ministries = Ministries.objects.all()
connect = Connect.objects.all()
context = {
'template': 'home',
'connect': connect,
'about': about,
'staff': staff,
'ministries': ministries,
}
return render(request,'home/index.html', context)
template(index.html):
<div class="connect-wrapper row">
<h1 class="title connect-title">Connect</h1>
{% for object in connect %}
<div class="home-div connect-div col-md-4">
<h4>{{ object.title }}</h4>
<p>{{ object.short_description }}</p>
{% if object.image %}
<img class="connect-image-home" src="{{object.image.url}}" alt="connect">
<p>{{object.image.url}}</p> //sanity check
{% endif %}
</div>
{% endfor %}
</div>
settings.py:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('home.urls'), name="home"),
]
I believe you need to add the media urls to your urls.py. Something like:
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('home.urls'), name="home"),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
On production environment Django does not load the media root automatically so that we can we can overcome that issue by adding following after url patterns:
urlpatterns = [
''''
your urls
''''
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
If you are using more than one app and including app urls on main app url, just add this on main project url.