Upload image in Django for specific user - python-3.x

I am trying to upload pic for specific user but nothing happened when i select image and upload it . it not store in db and not even in media folder
setting.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
View.py
def uploadPic(request):
if request.method == 'POST' and 'SESSION_KEY' in request.session:
form = Profile(
user_id=request.session['SESSION_KEY'],
profile_pic=ProfileForm(request.POST, request.FILES)
)
form.save()
return redirect('home')
else:
form = ProfileForm()
return render(request, 'upload.html', {
'form': form
})
Model.py
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile_pic = models.ImageField(null=True, blank=True, upload_to='image/')
Form.py
class ProfileForm(forms.ModelForm):
class Meta:
model = ProfileModel
fields = ['profile_pic']
Template
{% extends 'home.html'%}
{% block content %}
{%if user.is_authenticated%}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
{% endif %}
{% endblock %}

Firstly in your form you set model = ProfileModel but your model is Profile correct that:
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['profile_pic']
Next in your view in case of a POST request your view is completely wrong. You try to make an instance of Profile and call it form and save it. This is likely failing. Also I assume you write 'SESSION_KEY' in request.session in an attempt to check if the user is logged in, instead use request.user.is_authenticated or in fact disallow anonymous users from accessing your views by using the login_required decorator. Change it like so:
from django.contrib.auth.decorators import login_required
#login_required
def uploadPic(request):
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('home')
else:
form = ProfileForm()
return render(request, 'upload.html', {'form': form})
Note: The indentation of my answer is 4 spaces which is different from your indentation. It is best to indent by 4 spaces for readability. Check about indentation in PEP 8 which is the Style Guide for Python Code.

Related

Display images one by one when user clicks next in Django

I have created a django app where user uploads multiple pdf files and it converts to png and displays the images. I am using ModelForms for this purpose. The upload and the convert part is working fine but how do I display the Images sequentially?
What I want is to display one image and when the user clicks next, the next image should be displayed. Below is my app code:
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserUploadModel(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE, null = True)
file = models.FileField(upload_to = 'file_uploads/%d%m%Y')
views.py
from django.shortcuts import render, redirect
from app1.forms import UserUploadForm
from app1.models import UserUploadModel
from app1.convert import convert_file
from app1.transfer import move_dir
import os
from project1 import settings
# Create your views here.
def home(request):
if request.method == 'POST':
form = UserUploadForm(request.POST, request.FILES)
if form.is_valid():
f = form.save()
f.user = request.user
f.save()
ff = request.FILES.getlist('file')
f_list = []
for i in ff:
file_instance = UserUploadModel(file = i)
file_instance.save()
f_list.append(file_instance.file.path)
[convert_file(j) for j in f_list]
src_dir = os.getcwd()
dest_dir = os.path.join(src_dir, 'media/converted_files')
move_dir(src_dir, dest_dir, '*.png')
return redirect('app1-display')
else:
form = UserUploadForm()
return render(request, 'app1/home.html', {'form' : form})
def display(request):
return render(request, 'app1/display.html')
home.html
{%extends "app1/base.html"%}
{%block content%}
<form method="POST" enctype="multipart/form-data">
{%csrf_token%}
{{form.as_p}}
<input type="submit">
</form>
{%endblock content%}
You can display all user's image in your template and then use javascript to hide and show images :
app1/display.html
{% extends "app1/base.html" %}
{% block content %}
{% for image in request.user.useruploadmodel_set.all %}
<image src={{ image.url }} style="width: 100%{% if not forloop.first %}; display: none{% endif %}" />
{% endfor %}
<button id="nextBtn">Next</button
<script>
$(() => {
$("#nextBtn").click(() => {
$('image:visible').hide().next().show()
})
})
</script>
{% endblock %}
I've used jquery because I'm more used to it but that could be done with another framework or vanilla JS.
Why not using a JS carousel library ?

How to access a post author's profile picture in Django?

I am trying to display a username's profile picture in a blog/social media app when some user clicks on some other user's username but it is currently not working.
In my template: (I think my issue is I don't have access to post?)
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="img-thumbnail account-img mt-3 " src="{{ username.profile.image.url }}">
</article>
<h1 class="mb-3">Posts by {{ view.kwargs.username }} ({{ page_obj.paginator.count }})</h1>
<div class="infinite-container">
{% for post in posts %}
<div class="infinite-item">
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}">
<!-- profile (model in user ).image (attribute) -->
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"F d, Y" }}</small>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
</div>
{% endfor %}
</div>
My users\models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
In my blog/models.py:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
I can retrieve some user's username by {{ view.kwargs.username }}, how can I do this with profile pictures?
my blog\views.py:
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.db.models import Q
from .models import Post #from the model file in the current package import the Post class
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
def home(request):
context = {
'posts': Post.objects.all(), # querying the database
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_posts.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
paginate_by = 5
def get_queryset(self):
# it will get that user form that database if it exist, if user doesn't exist return 404,
# we are also using the User model, so need to import it
# 2nd parameter means that we are getting the username from the url
user = get_object_or_404(User, username=self.kwargs.get('username'))
# showing the posts by that specific user only
return Post.objects.filter(author=user).order_by('-date_posted')
# Looking at individual post
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html', {'title': 'About'})
def search(request):
if request.method == "POST":
searched = request.POST['searched']
posts = Post.objects.filter(
Q(title__icontains=searched) |
Q(author__username__icontains=searched))
usernames = []
for post in posts:
usernames.append(post.author)
# remove duplicates of username
usernames = list(set(usernames))
context = {'searched': searched, 'posts': posts, 'usernames': usernames}
return render(request, 'blog/search.html', context)
else:
return render(request, 'blog/search.html', {})
Use ForeignKey instead of OneToOneField. Add a related_name:
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="profile")
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
in html:
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}">
You can write a custom method also.
e.g:
class Post(models.Model):
...
author = models.ForeignKey(User, on_delete=models.CASCADE)
...
def get_owner_pp(self):
return self.author.profile.image.url
in html:
<img class="rounded-circle article-img" src="{{ post.get_owner_pp }}">

The page does not display information about created links in the admin panel. Django

The page should display a feedback form and links created in the admin panel. Created models:
from django.db import models
class ContactModel(models.Model):
# feedback form
name = models.CharField(max_length=50)
email = models.EmailField()
website = models.URLField()
message = models.TextField(max_length=5000)
create_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.name} - {self.email}'
class ContactLink(models.Model):
# links
icon = models.FileField(upload_to='icons/')
name = models.CharField(max_length=200)
def __str__(self):
return self.name
I connected the models to the admin panel:
from django.contrib import admin
from .models import ContactModel, ContactLink
#admin.register(ContactModel)
class ContactModelAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'email', 'create_at']
list_display_links = ('name',)
admin.site.register(ContactLink)
Everything works correctly, you can create links in the admin panel.
Below views.py:
from django.shortcuts import render
from django.views import View
from .models import ContactLink
class ContactView(View):
def get(self, request):
contacts = ContactLink.objects.all()
form = ContactForm()
return render(request, 'contact/contact.html', {'contact': contacts, 'form': form})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('contact/', views.ContactView.as_view(), name='contact'),
path('feedback/', views.CreateContact.as_view(), name='feedback'),
]
I go through the for loop through the code to return links from the admin panel:
#links
<div class="contact__widget">
<ul>
{% for contact in contacts %}
<li>
<img src="{{ contact.icon.url }}">
<span>{{ contact.name }}</span>
</li>
{% endfor %}
</ul>
</div>
#feedback form
<form action="{% url 'feedback' %}" method="post">
{{ form }}
<button type="submit" class="site-btn">Submit</button>
</form>
The Feedback form works fine, but links are not displayed at all on the page... Where could the error be?
Screenshot
The view must reference to the correct variable name. Use contact with an s in:
return render(request, 'contact/contact.html', {'contacts': contacts, 'form': form})

Django author Form not saving to database

models.py
class Blog(models.Model):
title = models.CharField(max_length=100, unique=True)
slug = models.CharField(max_length=100, unique=True)
post_pic = models.ImageField(upload_to ='media/post_pics/', default =None )
body = models.TextField()
posted = models.DateTimeField(db_index=True, auto_now_add=True)
#author = must be logged in, populate from login details
forms.py
class postForm(forms.Form):
title = forms.CharField(max_length=100)
slug = forms.CharField(max_length=100)
post_pic = forms.ImageField()
body = forms.CharField(widget=SummernoteWidget())
views.py
def write_detail(request):
template_name = 'blog/write.html'
if request.method == 'POST':
post_form = postForm(request.POST)
if post_form.is_valid():
new_post = Blog(title=title,slug=slug,post_pic=post_pic,body=body)
new_post.save()
return HttpResponseRedirect(blog.get_absolute_url())
else:
post_form = postForm()
return render(request, template_name, {'post_form': post_form})
write.html
{% extends 'blog/base.html' %}
{% load static %}
{% block back-img %}'{% static 'blog/assets/img/intro.jpg' %}'{% endblock back-img %}
{% block titdes %}Write{% endblock titdes %}
{% block title %}Write{% endblock title %}
{% block pagedes %}A django powered community blog{% endblock pagedes %}
{% block body%}
<form method = "POST">
{{ post_form.as_p }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Publish</button>
</form>
{% endblock %}
I have set up this form so that authors can write articles to the blog without accessing the admin panel and I believe it should work but it isn't saving to the database.
I have tried to work on the views over and over but don't know what else to do. Please don't delete my question just ask any question that can help you help me.
in your forms.py
try
from .models import Blog
class postForm(forms.Form):
title = forms.CharField(max_length=100)
slug = forms.CharField(max_length=100)
post_pic = forms.ImageField()
body = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic', 'body')
PS. Iam new to Django, i hope this help you.
It looks like you just need to save the form, but you're creating a new Blog object with values that we can't see defined anywhere.
new_post = Blog(title=title,slug=slug,post_pic=post_pic,body=body)
title, slug, etc don't get defined.
What you should do, is change it to a ModelForm so that django does all the hard work;
class postForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic', 'body')
widgets = {
'body': SummernoteWidget(),
}
Then in your view you just need to do;
def write_detail(request):
template_name = 'blog/write.html'
if request.method == 'POST':
post_form = postForm(request.POST)
if post_form.is_valid():
post_form.save()
return HttpResponseRedirect(blog.get_absolute_url())
else:
# GET request
post_form = postForm()
return render(request, template_name, {'post_form': post_form})
The summernote docs for forms (and modelforms) is here
Don't forget, that when using a widget like this that comes with media, you need to add the form's media to the template.
You can access it in the HTML using either {{ form.media }} to get all CSS and JS, or individually as {{ form.media.js }} and {{ form.media.css }}
You can see how they do it in the summernote app playground
class postForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic','body')
widgets = {
'body':SummernoteWidget(),
}
Sorry guys you can actually use django summer note with a model form. I used it before but the editor was not appearing so I changed it to the one I previously posted but after reading another answer on stack overflow. I found out that I didn't add this code below to my HTML files or just inside my base.html
<!-- include summernote css/js-->
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.js"></script>
Thanks guys

ModelForm Fields are not pre-populated with existing data during updating in Django

I want to update the User and Lab model. I am able to see the form but it is not pre-populated with existing database information even after setting the instance parameter. If I submit a blank form then all fields are reset to blank values in the database. I have tried several solutions available online but nothing works.
My queries -
How do I pre-populate my form with existing data?
If the user doesnt fill out a particular field, I want the previous information to be stored as it is and not as a blank value. How do I achieve this?
I have the following models.py
class Lab(models.Model):
uid = models.OneToOneField(User, on_delete=models.CASCADE)
company=models.CharField(max_length=200,blank=True)
#receiver(post_save, sender=User)
def create_lab_profile(sender, instance, created, **kwargs):
if created:
Lab.objects.create(uid=instance)
#receiver(post_save, sender=User)
def save_lab_profile(sender, instance, **kwargs):
instance.lab.save()
Forms.py
class UserForm(forms.ModelForm):
email=forms.EmailField(max_length=300)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email',)
class LabForm(forms.ModelForm):
class Meta:
model = Lab
fields = ('company',)
views.py
#login_required
def update_user_details(request,pk):
if request.method == 'POST':
user_form = UserForm(request.POST,instance=request.user)
lab_form = LabForm(request.POST,instance=request.user.lab)
if user_form.is_valid() and lab_form.is_valid():
user_form.save()
lab_form.save()
messages.success(request,'Your profile was successfully updated!')
return redirect('user_details')
else:
messages.error(request,('Please correct the error below.'))
else:
user_form = UserForm(instance=request.user)
lab_form = LabForm(instance=request.user.lab)
return render(request, 'update_user_details.html', {'user_form': user_form,'lab_form': lab_form})
template -
{% extends 'base.html' %}
{% block content %}
{% csrf_token %}
<H3> Update Personal information - </H3>
<br>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
{{ lab_form.as_p }}
<button type="submit" class="btn btn-primary">Save changes</button>
</form>
{% endblock %}
Any help/suggestions will be appreciated!

Resources