Display Profile Picture of Users - django

I am trying to display the profile pictures of new users registered to a website to show to every user logged onto the website and so far i have been able to display their username but i am having difficulty displaying their profile picture stored in an extended model User profile. How do i make this happen to display it in my templates. A better solution is welcome
Profile_tag
def person(context, e):
"""
Renders a single user object.
"""
to_return = {
'user': context ['user'],
'profile': context['UserProfile.objects.all'],
}
register = template.Library()
register.inclusion_tag('profile/person.html', takes_context=True)(person)
Person.html
<div class="person">
<a href="{% url 'profile_detail' user.username %}">
<span class="username">{{ user.username|slice:"12" }}</span>
<p> <img src="/static/assets/{{profile_picture}}" height="100" width="100"></p>
</a>
</div>
user_list.html
{% load profile_tags %}
{% block main_content %}
<h1>Newest Users</h1>
{% friends_for_user user as friend_dict %}
{% for person in object_list %}
{% dict_entry_for_item person.username from friend_dict as friend %}
{% person person %}
{% ifnotequal person user %}
<form method="POST" action="{% if friend %}{% url 'sg_unfollow' person.username %}{% else %}{% url 'sg_follow' person.username %}{% endif %}">{%csrf_token%}
<input type="submit" value="{% if friend %}Unfollow{% else %}Follow{% endif %}" />
</form>
{% endifnotequal %}
{% endfor %}
Urls.py
urlpatterns = patterns('profile.views',
url(r'^detail/(?P<username>[a-zA-Z0-9_-]+)/$', 'detail',
name='profile_detail'),
)

profile_picture came from where ?
Extended user model Profile user Foreignkey with User then
models.py
class Profile(models.Model):
user = models.ForeignKey(User)
profile_picture = models.ImageField(upload_to='uploads/avatar')
views.py
userDetail = Profile.objects.get(user_id=request.session['_auth_user_id'])
templateVar['profile_picture'] = userDetail.profile_picture

Related

Only Show Edit Button On Owner's Posts - Django

I have a Django project with posts and the ability to edit posts.
On the main index page, I am showing all posts, like a news feed.
Currently anyone can edit any post, but I want to make it so that only the owner of the post can edit. I'm just not sure how to write the urls.py file since I'm using:
path("", views.index, name="index"),
I would probably need to pass either the post id or the username to this, but I'm not sure how to write it. I tried:
path("index", views.index, name="index"),
path("index/<str:pk>", views.index, name="index"),
path("index/<str:username>", views.index, name="index"),
But I get errors.
views.py
def index(request):
list_of_posts = Post.objects.all().order_by('id').reverse()
paginator = Paginator(list_of_posts, 10)
num = request.GET.get('page', 1)
get_page_num = paginator.get_page(num)
return render(request, "network/index.html", {
"list_of_posts": list_of_posts,
"get_page_num": get_page_num,
})
models.py
class User(AbstractUser):
pass
class Post(models.Model):
text = models.TextField(max_length=500, blank=True,
null=True)
username = models.ForeignKey('User',
on_delete=models.CASCADE, related_name='author',
null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)
like = models.ManyToManyField(
User, blank=True, related_name="liked_user")
def __str__(self):
return self.username.username
html to show edit button. I've tried:
{% if post.username == request.user.username %}
<button class="btn-btn primary" my-id="{{i.id}}" id="ebutton-
{{i.id}}" onclick="edit_form(this)" >Edit</button>
<br><br><br>
{% endif %}
Full html of this page:
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
<br>
<h3> <center> Welcome. Here is your news feed: </center> </h3>
<br>
{% for i in get_page_num %}
<div class='card mb-3' style="max-width: 530px;" id="card-posts">
<div class="row no-gutters">
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title"><a href="{% url 'profile'
username=i.username %}">{{i.username}}</a></h5>
<span id="textinfo-{{i.id}}"
class="post">{{i.text}}</span> <br>
<textarea my-id="{{i.id}}" id="edit-me-{{i.id}}"
style="display:none;" class="form-control
textarea" row="3">{{i.text}}</textarea>
<br>
<p class="card-text">{{i.timestamp}}</p>
<div class="like mt-1">
<img my-id="{{i.id}}" id="is-it-liked-{{i.id}}"
class="like-class"
{% if not request.user in i.like.all %}
clicked="no"
src="https://img.icons8.com/emoji/452/white-heart.png"
{%else%}
clicked="yes"
src="https://img.icons8.com/emoji/452/red-heart.png"
{%endif%}
/> <span id="post-count-{{i.id}}">{{i.like.count}}.
</span>
</div>
<br>
{% if request.user == post.username %}
<button class="btn-btn primary" my-id="{{i.id}}"
id="ebutton-{{i.id}}" onclick="edit_form(this)"
>Edit</button>
<br><br><br>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
<br><br>
<div class="pagination">
<span class="step-links">
{% if get_page_num.has_previous %}
<a href="?page={{ get_page_num.previous_page_number }}"
class="page-link">Previous</a>
{% else %}
<li class="page-item disabled"><a class="page-
link">Previous</a></li>
{% endif %}
{% if get_page_num.has_next %}
<a href="?page={{ get_page_num.next_page_number }}" class="page-
link">Next</a>
{% else %}
<a class="page-link">Next</a>
{% endif %}
</span>
</div>
{% endblock %}
{% block script %} <script src="{% static
'network/network.js'%}"></script> {% endblock %}
With this way I need to pass username to the url but I cannot, without getting errors.
Overall I'm just looking for advice, on how to make the edit button only appear on posts that the current user is an owner on. So that way no one can edit anyone else's posts.
If you want to show all posts and only allow a post author to edit it, you need to inject all posts and the request user in your template context. Then in your template iterate through the posts and check if the author is equal to the request user before showing the edit button. But first you need a foreign key in your post model that refers to the author.
Urls.py
urlpatterns = [path("index/", views.index, name="index")]
Views
def index(request):
list_of_posts = Post.objects.order_by('-id')
request_user = request.user
return render(request, "network/index.html", {
"list_of_posts": list_of_posts,
"request_user": request_user
})
Models
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='posts')
# Other fields
Template
{% if post.user == request_user %}
<!--Show the edit button-->
{% endif %}
You can also access directly the request object in your template:
{% if post.user == request.user %}
<!--Show the edit button-->
{% endif %}
I needed to add
{% if request.user == i.username %}
because I was looping in the html page, for i in get_page_num:. I did not previously have the i.
{% if request.user == post.author %}
<button>Delete</button>
{% endif %}
This assumes that you have a Post model with an attribute of author

Django simple search with Class based views and forms.py

I have been trying to do a variation of what Williams Vincent did on this page: https://learndjango.com/tutorials/django-search-tutorial .
I am using Django 3.2 so if there are modifications, I need to make I have not identified them. I am having some troubles.
This what I made which worked just fine.
my_search.html:
{% extends "base.html" %}
{% block body %}
{% for city in object_list %}
<li>
{{city.name}}   {{city.city_no}}
</li>
{% endfor %}
{% endblock %}
views.py:
from django.views.generic import ListView
from .models import City
class SearchResutlsView(ListView): # test version
model = City
template_name = "search_results.html"
def get_queryset(self):
return City.objects.filter(name__icontains='Boston')
Now it is time to add forms.py, but when I made the below changes to the code it does not work. What am I missing? There are no errors displayed. I get a blank html.
{% extends "base.html" %}
{% block body %}
<form class="d-flex" method='get' action="{% url 'city:search_results' %}">
{{ form }}
<button class="btn btn-outline-success" type="submit" value="qu">Search Name</button>
</form>
{% for city in city_list %}
<li>
{{city.name}}   {{city.city_no}}
</li>
{% endfor %}
{% endblock %}
forms.py
from django import forms
class SearchForm(forms.Form):
q = forms.CharField(label='Search label', max_length=50, strip=True)
views.py
from django.views.generic import FormView, ListView
from .models import City
class SearchResutlsView(FormView):
model = City
form_class = SearchForm
template_name = "city/search_results.html"
def get_queryset(self):
query = self.request.Get.get("q")
if query:
city_list = City.objects.filter(name__icontains=query)
else:
city_list = City.objects.none()
return city_list
First, Your method should be POST not get.
Second, you need to add CSRF token.
something like that:
{% extends "base.html" %}
{% block body %}
<form class="d-flex" method='post' action="{% url 'city:search_results' %}">
{% csrf_token %}
{{ form }}
<button class="btn btn-outline-success" type="submit" value="qu">Search Name</button>
</form>
{% for city in city_list %}
<li>
{{city.name}}   {{city.city_no}}
</li>
{% endfor %}
{% endblock %}
and in views.py
query = self.request.POST.get("q")

Why is my Update URL link kicking me to the CreateNew html view

so this is a tag on from my previous stackoverflow post:
Django updateView saving another instance instead of updating
and i think i've narrowed it down. Whats happening is that when i click on the link to update my view, it sends me to the "create new" page. my problem is that I cant figure out why its doing that.
Any and all help is appreciated.
here is the code:
question_form.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Create New Question</h4>
<form method="POST" action="{% url 'questions:create' %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Post" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_update.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'questions:update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_detail.html
{% block content %}
this is the question detail view
<h3>{{ question.question_html|safe }}</h3>
<h3>{{ question.answer_html|safe }}</h3>
Update Question
{% endblock %}
urls.py
url(r'new/$', views.CreateQuestion.as_view(), name='create'),
url(r'questionupdate/(?P<pk>\d+)/$', views.QuestionUpdate.as_view(), name='update'),
url(r'questiondetail/(?P<pk>\d+)/$', views.QuestionDetail.as_view(), name='single'),
views.py
class CreateQuestion(generic.CreateView):
model = models.Question
form = QuestionForm
fields = ('question', 'answer')
success_url = reverse_lazy('questions:all')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class QuestionDetail(generic.DetailView):
model = models.Question
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
context_object_name = 'question'
From your urls.py the name of update view is only update. You can try only update tag in html file Like
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
I've figured it out. it turns out I was missing the template name part under my Create and update views which directs them to their own html templates:
class CreateQuestion(generic.CreateView):
model = models.Question
form_class = QuestionForm
fields = ('question', 'answer')
template_name = "questions/question_form_create.html"
success_url = reverse_lazy('questions:all')
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
template_name = "questions/question_form_update.html"

Django: How to show all images in images model

I am trying to show all images associated with the currently selected user
This is built off of this solved question: django upload to image model with foreign key to user
Model.py
class Images(models.Model):
image = models.ImageField(upload_to='profile_image', null=True, default='profile_image/none/no-img.png')
user = models.ForeignKey(User, on_delete=models.CASCADE)
Views.py
#login_required
def index_account(request):
args = {'user': request.user }
return render(request, 've/cp/index_account.html', args)
Template > index_account.html
<p>Edit your images</p>
# test to see if it worked w/o if
{{ user.images.image}}
# ideal solution
{% if user.images.images %}
{% for img in user.images %}
<img src="{{ user.images.image.url }}"><br>
{% endfor %}
{% else %}
<p>No images</p>
{% endif %}
<br>
<hr>
The code you have provided is not going to work for what you want. So here is an example of something that probably will:
Example
views.py
from app_name.models import Images
#login_required
def index_account(request):
images = Images.objects.filter(user=request.user)
return render(request, 've/cp/index_account.html', {"images": images})
index_account.html
<p>Edit your images</p>
# ideal solution
{% if images %}
{% for img in images %}
<img src="{{ img.url }}"><br>
{% endfor %}
{% else %}
<p>No images</p>
{% endif %}
<br>
<hr>
Hope this helps!

How to GET data by search word Django

I have problem getting the data to the home page.
I would like to filter out all the books based on Genre. I'm following the
MDN site for this.
index.html
{% extends "base_generic.html" %}
{% block content %}
<h1>Local Library Home</h1>
<p>Welcome to <em>Local Library</em>, a very basic Django website.</p>
<h2>Dynamic content</h2>
<form action="" method="get">
<input type="text" name="genre" placeholder="Search">
<input type="submit" value="Search">
</form>
{% endblock %}
urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^books/$', views.BookListView.as_view(), name='books'),
url(r'^(?P<string>[-\w]+)$', views.GenreListView.as_view(), name='index'),
]
GenreListView class
class GenreListView(generic.ListView):
model = Book
def get(request, string):
try:
book = Book.objects.all().filter(genre=string)
except Book.DoesNotExist:
raise Http404("Book does not exist")
return render(
request,
'index.html',
context={'book': book,}
)
I can't figure out what I'm missing or what else I have to do to get all the date based on genre?
EDIT:
whole index.html
{% extends "base_generic.html" %}
{% block content %}
<h1> Book List </h1>
<form action="" method="get">
<input type="text" name="genre" placeholder="Search">
<input type="submit" value="Search">
</form>
{% if book_list %}
<ul>
{% for book in book_list %}
<li>
{{ book.title }} ({{ book.author }})
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no books in the library</p>
{% endif %}
{% endblock %}
You should override get_queryset, No need to rewrite get
class GenreListView(generic.ListView):
model = Book
template_name = 'index.html'
def get_queryset(self):
books = Book.objects.all()
query = self.request.GET.get('genre', None)
if query:
return books.filter(genre=query)
return books
The exception Book.DoesNotExist will never
occur if you filter() queryset. it will always return a empty queryset in case of no object found