How to filter out Friends of user in search users function Django - django

I'm trying to filter out the friends of a user and also the current logged in user from a "search_users" function, I've tried using exclude() but keep getting an error I'm not sure whats wrong. I also wanted to add a "add friend" button next to the users, which I think I've done correctly on 'search_users.html.
Error
views.py
#login_required
def search_users(request):
query = request.GET.get('q')
object_list = User.objects.filter(username__icontains=query).exclude(friends=request.user.profile.friends.all())
context ={
'users': object_list
}
return render(request, "users/search_users.html", context)
search_users.html
{% extends "feed/layout.html" %} {% load static %}
{% block searchform %}
<form
class="form-inline my-2 my-lg-0 ml-5"
action="{% url 'search_users' %}"
method="get"
>
<input name="q" type="text" placeholder="Search users.." />
<button class="btn btn-success my-2 my-sm-0 ml-10" type="submit">
Search
</button>
</form>
{% endblock searchform %} {% block content %}
<div class="container">
<div class="row">
<div class="col-md-8">
{% if not users %}
<br /><br />
<h2><i>No such users found!</i></h2>
{% else %}
<div class="card card-signin my-5">
<div class="card-body">
{% for user_p in users %}
<a href="{{ user_p.profile.get_absolute_url }}"
><img
src="{{ user_p.profile.image.url }}"
class="rounded mr-2"
width="40"
height="40"
alt=""
/></a>
<a class="text-dark" href="{{ user_p.profile.get_absolute_url }}"
><b>{{ user_p }}</b></a
>
<small class="float-right">
<a
class="btn btn-primary mr-2"
href="/users/friend-request/send/{{ user_p.username }}"
>Add Friend</a>
</small>
<br/><br />
{% endfor %}
</div>
</div>
{% endif %}
</div>
<div class="col-md-4">
<div class="card card-signin my-5">
<a href="{{ request.user.profile.get_absolute_url }}"
><img
class="card-img-top"
src="{{ request.user.profile.image.url }}"
alt=""
/></a>
<div class="card-body">
<h5 class="card-title text-center">{{ request.user }}</h5>
<h6 class="text-center">
{{ request.user.profile.friends.count }}
<p class="text-muted">Friends</p>
</h6>
<p class="card-text text-center">{{ request.user.profile.bio }}</p>
</div>
</div>
</div>
</div>
{% endblock content %}
</div>
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png', upload_to='profile_pics')
slug = AutoSlugField(populate_from='user')
bio = models.CharField(max_length=255, blank=True)
friends = models.ManyToManyField('Profile', blank=True)

I would have done like this :
object_list = User.objects\
.filter(username__icontains=query)\
.exclude(profile__friends__in=request.user.profile.friends.all())\
.exclude(id=request.user.id)

It should be
User.profile.objects.filter(username__icontains=query).exclude(friends=request.user.profile.friends.all())
You were getting an error earlier because you referred to the user object earlier and not the profile itself. User.profile gives the one to one related model profile instead.
You can read more about one to one relationships here. https://docs.djangoproject.com/en/3.1/topics/db/examples/one_to_one/

Related

Problems with a backend part of search line in Django

who can explain me why my SearchView doesn't work. I have some code like this.It doesn't show me any mistakes, but it doesn't work. The page is clear. Seems like it doesn't see the input.
search.html
<div class="justify-content-center mb-3">
<div class="row">
<div class="col-md-8 offset-2">
<form action="{% url 'search' %}" method="get">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search..." />
<div class="input-group-append">
<button class="btn btn-dark" type="submit" id="button-addon2">Search</button>
</div>
</div>
</form>
</div>
</div>
</div>
search/urls.py
path('search/', SearchView.as_view(), name='search')
search/views.py
class SearchView(ListView):
model = Question
template_name = 'forum/question_list.html'
def get_queryset(self):
query = self.request.GET.get("q")
object_list = Question.objects.filter(
Q(title__icontains=query) | Q(detail__icontains=query)
)
return object_list
forum/question_list.html
{% extends 'main/base.html' %}
{% block content %}
{% for question in object_list %}
<div class="card mb-3">
<div class="card-body">
<h4 class="card-title">{{ question.title }}</h4>
<p class="card-text">{{ question.detail }}</p>
<p>
{{ question.user.username }}
5 answers
10 comments
</p>
</div>
</div>
{% endfor %}
{% endblock %}

My for loop does not work as expected - Data does not show up in my django template

I am trying to use a for loop in my Django template to show the data stored in the models of a table but for some reason , the data does not show up in the template.
Views.py
def add_part(request):
parts = Parts.objects.all()
context = {
"parts": parts
}
return render(request, 'admintemplate/add_parts_template.html', context)
def add_part_save(request):
if request.method != "POST":
messages.error(request, "Method Not Allowed!")
return redirect('add_part')
else:
part_name = request.POST.get('part_name')
part_type = request.POST.get('part_type')
supplier_id = request.POST.get('suppliers')
suppliers = Suppliers.objects.get(id=supplier_id)
try:
part = Parts(part_name=part_name, part_type=part_type, supplier_id=supplier)
part.save()
messages.success(request, "Part Added Successfully!")
return redirect('add_part')
except:
messages.error(request, "Failed to Add Part!")
return redirect('add_part')
models.py
The parts and the services model are exactly the same with different column names, so I think the functionality for both should be the same.
Suppliers models
class Suppliers(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
Parts model
class Parts(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
part_type = models.CharField(max_length=20)
supplier_id = models.ForeignKey(Suppliers, on_delete=models.CASCADE)
Services model
class Services(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
service_type = models.CharField(max_length=20)
supplier_id = models.ForeignKey(Suppliers, on_delete=models.CASCADE)
Part template
{% extends 'admintemplate/base_template.html' %}
{% block page_title %}
Add Parts
{% endblock page_title %}
{% block main_content %}
{% load static %}
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<!-- general form elements -->
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Add Parts</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
<form role="form" method="POST" action="{% url 'add_part_save' %}">
{% csrf_token %}
{% comment %} Display Messages {% endcomment %}
{% if messages %}
<div class="form-group">
<div class="col-12">
{% for message in messages %}
{% if message.tags == "error" %}
<div class="alert alert-danger alert-dismissible fade show" role="alert" style="margin-top: 10px;">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% elif message.tags == "success" %}
<div class="alert alert-success alert-dismissible fade show" role="alert" style="margin-top: 10px;">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="card-body">
<div class="form-group">
<label>Part Name </label>
<input type="text" class="form-control" name="part_name" placeholder="Part Name">
</div>
<div class="form-group">
<label>Part Type </label>
<input type="text" class="form-control" name="part_type" placeholder="Part Type">
</div>
<div class="form-group">
<label>Supplier Name</label>
<select class="form-control" name="suppliers">
{% for supplier in suppliers %}
<option value="{{ supplier.id }}">{{ supplier.name }}</option>
{% endfor %}
</select>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">Add Part</button>
</div>
</form>
</div>
<!-- /.card -->
</div>
</div>
</div><!-- /.container-fluid -->
</section>
{% endblock main_content %}
Now the services in parts template does not show up at all. There is no choices on the form. But, for the add services template, it does populate. I have no idea why this happens because I have used the exact same code for both templates.
Changing the view to this solved the issue
def add_part(request):
parts = Parts.objects.all()
context = {
"suppliers": suppliers
}
return render(request, 'admintemplate/add_parts_template.html', context)

How to delete multiple objects in django?

I am trying to delete django model multiple objects using html checkboxes but i can't. Kindly guide me what I need to do complete my this task.
I try the following code for this purpose but i failed.
views.py
class DeleteProducts(SuccessMessageMixin, View):
success_url = reverse_lazy('stock:stock')
success_message = "Products are deleted successfully."
def post(self, request, *args, **kwargs):
products = self.request.POST.getlist('product')
Product.objects.filter(pk__in=products).delete()
messages.success(self.request, self.success_message, extra_tags='alert-danger')
return redirect('stock:stock')
In template i used checkboxes prefectly or not??
template.html
<form method="POST" action="{% url 'stock:deleteproducts' %}">
{% csrf_token %}
{% for product in page_obj %}
<div class="row" >
<input type="checkbox" value="{{ product.id }}">
<div class="col-sm-2" >
<h5>{{ product.id }}</h5>
<img src="{{ product.Picture.url }}" height="120px" />
</div>
<div class="col-sm-4" >
<h5><u>Product Name</u>: {{ product.pro_name }}</h5>
<h6><u>Company Name</u>: {{product.companyName}}</h6>
<div class="row" >
<div class="col-sm" >
<p>Purchase Price: <b>{{product.Purchase_Price}}</b></p>
</div>
<div class="col-sm" >
<p class="pt-0">Sale Price: <b>{{product.Sale_Price}}</b> </p>
</div>
</div>
<div class="row" >
<div class="col-sm" >
<p>Quantity <b>{{product.Quantity}}</b></p>
</div>
<div class="col-sm" >
<p> Added By: <b>{{product.saler}}</b> </p>
</div>
</div>
</div>
<div class="col-sm-4" >
<p><b>Added Date</b>:{{ product.pub_date }}</p>
<hr/>
<center>
<a href="{% url 'stock:editproduct' product.id %}" class="btn btn-success" >Edit</a>
</center>
</div>
</div>
<hr/>
{% endfor %}
<input type="submit" class="btn btn-danger" value="Delete" >
</form>
urls.py
path('delete/', login_required(DeleteProducts.as_view(), login_url='login'), name='deleteproducts'),
You need to assign name="product" attribute to checkboxes since you are trying to get it with self.request.POST.getlist('product'):
<input type="checkbox" value="{{ product.id }}" name="product">

Image ids apparently not being created

I have created a template for displaying a photo gallery and giving users the ability to add photos to that gallery:
{% extends 'nowandthen/base.html' %}
{% block body_block %}
<br>
<br>
{% if pictures %}
<ul>
{% for p in pictures %}
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 ">
<!-- Card -->
<!-- Card content -->
<div class="card-body d-flex flex-row">
<!-- Content -->
<div>
<!-- Title -->
<h4 class="card-title font-weight-bold mb-2">{{ p.title }}</h4>
<!-- Subtitle -->
<p class="card-text"><i class="far fa-clock pr-2"></i>{{ p.when_added }}</p>
</div>
</div>
<!-- Card image -->
<div class="view overlay">
<img class="card-img-top rounded-0" src="{{ p.image.url }}" alt="Card image cap">
<a href="#!">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!-- Card content -->
<div class="card-body">
<div class="collapse-content">
<!-- Text -->
<p class="card-text collapse" id="collapseContent">{{ p.description }}</p>
<!-- Button -->
<a class="btn btn-flat red-text p-1 my-1 mr-0 mml-1 collapsed" data-toggle="collapse" href="#collapseContent" aria-expanded="false" aria-controls="collapseContent">Click for description</a>
<i class="fas fa-share-alt text-muted float-right p-1 my-1" data-toggle="tooltip" data-placement="top" title="Share this post"></i>
<i class="fas fa-heart text-muted float-right p-1 my-1 mr-3" data-toggle="tooltip" data-placement="top" title="I like it"></i>
</div>
</div>
<div class="card-body">
<!-- comments -->
<h2>comments</h2>
{% if not p.comments %}
No comments
{% endif %}
{% for x in p.comment %}
<div class="comments" style="padding: 10px;">
<p class="font-weight-bold">
<h4>Comment by</h4> {{ x.user }}
<span class=" text-muted font-weight-normal">
{{ x.created_on }}
</span>
</p>
{{ x.body | linebreaks }}
</div>
{% endfor %}
</div>
<div class="card-body">
{% if new_comment %}
<h2>Your comment has been posted.</h2>
{% else %}
<h3>Leave a comment</h3>
<form action="{% url 'nowandthen:add_comment' p.image_id %}" method="POST">
{{ comment_form.as_p }}
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Card -->
{% endfor %}
</ul>
{% else %}
<li><strong>There are no photographs present.</strong></li>
{% endif %}
{% endblock %}
The idea is that there is an image associated with each comment - there is a for loop of {% for p in pictures %} at the start of the page, and I use variations of p. (e.g. p.image_id) to associate particular pictures with particular comments.
In addition, the urls.py contains the following:
path('add_comment/<int:p.image_id>', views.add_comment, name='add_comment')
However, when I run the code, I get an error message that suggests that image ids aren't being created (even though image is a field in he Pictures model I created):
Reverse for 'add_comment' with arguments '('',)' not found. 1 pattern(s) tried: ['add_comment/$']
What do you suggest, please?
EDIT: This is my view:
#login_required
def add_comment(request, image_id):
new_comment = None
template_name = 'add_comment.html'
image = get_object_or_404(Picture, id=image_id)
comment = image.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object and don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
context = {'image': image,'comment': comment, 'new_comment': new_comment,'comment_form': comment_form}
return render(request, template_name, context)
And this is my add_comment.html template:
{% extends 'nowandthen/base.html' %}
{% load staticfiles %}
{% block title_block %}
Add self
{% endblock %}
{% block body_block %}
<h1>Add a Comment</h1>
<div>
<form id="comment_form" method="post" action="{% url 'nowandthen:add_comment' comment_id%}" enctype="multipart/form-data" >
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value="Add Comment" />
</form>
</div>
{% endblock %}
Since you pictures variable is a Queryset, when you loop through it in your template, to access its ID, you just need to do it that way. instance.id
Based on your case, you will have:
{% url 'nowandthen:add_comment' p.id %}
And you will be able to access the id in your view with image_id

Blog Post doesn't show images, bold text, or other attributes only the raw code... Django/Ckeditor

I've followed a tutorial on implementing a ckeditor RichTextUploadingField() to my blog so I can have more functionality and better looking post/blogs.
Everything seems to be working but when I go to see the actual post after adding the picture and some words. I get a raw output with all my text...
Here is my output on my blog
<p><span style="color:#1a1a1a"><span style="background-color:#ffffff">First of all, I have assumed that you have seen countless rubbish articles, and still can't understand classes and objects, but at least know that there are two things like classes and objects.</span></span></p>
<p><span style="color:#1a1a1a"><span style="background-color:#ffffff">Since you don't have programming experience, you can't understand Python's 'classes and objects' by analogy from the programming language you've learned. Let's use the example of life to build a house.</span></span></p>
<p> </p>
<p><span style="color:#1a1a1a"><span style="background-color:#ffffff"><img alt="" src="/media/upload/2019/11/08/01.png" style="height:268px; width:400px" /></span></span></p>
Not sure why it doesn't look like the output I get before I post the article while I'm editing and creating it.
MODELS.PY
from ckeditor_uploader.fields import RichTextUploadingField
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=100)
# content = models.TextField()
content = RichTextUploadingField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.title} --> {self.author}'
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
POST_DETAIL.HTML
{% extends "portfolio_app/base.html" %}
{% block content %}
<div class="py-5 bg-light">
<div class="container">
<div class="row">
<div class="col-md-12">
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:'F d, Y' }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update Post</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete Post</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
</div>
</div>
</div>
</div>
{% endblock content %}
POST_FORM.HTML
{% extends "portfolio_app/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container col-md-6">
<div class="content-section">
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom md-4">Blog Post</legend>
{{ form.media }}
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post!</button>
</div>
</form>
</div>
</div>
</div>
{% endblock content %}
Am I missing something..? Thank you again for your help.
use |safe filter.
<h2 class="article-title">{{ object.title|safe }}</h2>
<p class="article-content">{{ object.content|safe }}</p>