Want to print all groups to which user belongs - django

**Models.py**
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
def get_absolute_url(self):
return reverse("accounts:login")
class Group(models.Model):
name = models.CharField(max_length = 255,unique = True)
slug = models.SlugField(allow_unicode = True,unique = True)
description = models.TextField(default = '')
members = models.ManyToManyField(User,related_name = "group")
def save(self,*args,**kwargs):
self.slug = slugify(self.name)
super(Group,self).save(*args,**kwargs)
def get_absolute_url(self):
return reverse('groups:single',kwargs = {'slug':self.slug})
def __str__(self):
return self.name
**Views.py**
class ListGroups(ListView):
model = Group
**Html code**
<div class="col-md-8">
<div class="list-group">
{% if user.is_authenticated %}
<h2>Your Groups!</h2>
{% if user.group.count == 0 %}
<p>You have not joined any groups yet! <p>
{% else %}
{% for group in user.group.all %}
<a class="list-group-item" href="{% url 'groups:single' slug=group.slug %}">
<h3 class="list-group-item-heading">{{group.name}}</h3>
<div class="list-group-item-text container-fluid">
{{group.description|safe}}
<div class="row">
<div class="col-md-4">
<span class='badge'>{{group.members.count}}</span>
member{{group.members.count|pluralize}}
</div>
<div class="col-md-4">
<span class='badge'>{{group.posts.count}}</span>
post{{group.posts.count|pluralize}}
</div>
</div>
</div>
</a>
{% endfor %}
{% endif %}
{% endif %}
</div>
According to me it should print all the groups and it's details to which current logined user belongs but it is not printing anything.I have no idea what is wrong in this code.I have tried some other approaches but nothing works.Can anyone help?
Thanks in advance.

Well there is no variable named user in the template, hence all what you wrote will probably not work.
We can however obtain a list of Groups where the logged in user is member of, by first of all modifying the ListsGroup a bit:
from django.contrib.auth.mixins import LoginRequiredMixin
class ListGroups(LoginRequiredMixin, ListView):
model = Group
def get_queryset(self):
return Group.objects.filter(members=self.request.user)
Now we can render this like:
<div class="col-md-8">
<div class="list-group">
<h2>Your Groups!</h2>
{% for group in object_list %}
<a class="list-group-item" href="{% url 'groups:single' slug=group.slug %}">
<h3 class="list-group-item-heading">{{group.name}}</h3>
<div class="list-group-item-text container-fluid">
{{group.description|safe}}
<div class="row">
<div class="col-md-4">
<span class='badge'>{{group.members.count}}</span>
member{{group.members.count|pluralize}}
</div>
<div class="col-md-4">
<span class='badge'>{{group.posts.count}}</span>
post{{group.posts.count|pluralize}}
</div>
</div>
</div>
</a>
{% empty %}
<p>You have not joined any groups yet! <p>
{% endfor %}
</div>

Related

Model infos not showing up on HTML page Django

I am trying to create an educational website using Django, so when I am trying to render {{ profile.institution }} or {{ profile.grade }} or {{ profile.user.username }} they are not being rendered.I don't know why they aren't. Can anyone help me solve this?
My models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
institution = models.CharField(max_length = 100)
grade = models.CharField(max_length=100, choices= YEAR_IN_SCHOOL_CHOICES)
bio = models.TextField(max_length=300)
def __str__(self):
return f'{self.user.username} Profile'
My views.py:
class User_Profile(LoginRequiredMixin, ListView):
model = Profile
template_name = 'class/profile.html'
context_object_name = 'profile'
def get_queryset(self):
return Profile.objects.filter(user=self.request.user)
My html:
{% extends "class/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<br>
<div class="row d-flex justify-content-center">
<h1 style="color: #f5a425">Hello {{ user.username }}</h1>
</div>
<div class="container mt-5">
<div class="row d-flex justify-content-center">
<div class="col-md-7">
<div class="card p-3 py-4">
<div class="text-center">
<i class='fas fa-user-alt' style='font-size:36px'></i>
<!-- <img src="" width="100" class="rounded-circle"> -->
</div>
<div class="text-center mt-3">
<span class="bg-secondary p-1 px-4 rounded text-white">Pro</span>
<h5 class="mt-2 mb-0">{{ profile.user.username }}</h5>
<span>{{ profile.institution }}</span>
<span>{{ profile.grade }} Grade</span>
<div class="px-4 mt-1">
<p class="fonts">{{ profile.bio }}</p>
</div>
<div class="buttons">
<button class="btn btn-outline-primary px-4">Message</button>
<button class="btn btn-primary px-4 ms-3">Contact</button>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
what part of the code should I change to make this work ?
ListView it is about many objects ant iteration through the object_list. In this case the answer of #PouyaEsmaeili is correct.
But. The mistake is - you have a wrong view. DetailView is the right choose.
This returns always one object or nothing.
Profile.objects.filter(user=self.request.user)
In your case:
class User_Profile(LoginRequiredMixin, DetailView):
model = Profile
template_name = 'class/profile.html'
context_object_name = 'profile'
def get_object(self):
return get_object_or_404(self.model, user=self.request.user)
If you set name for template profile_detail.html, you don't need template_name attribute. It should be find automatically.
If you don't change the model_name in Profile._meta - , you don't need context_object_name attribute. It should be defined automatically.
Please, don't forget about Django-views naming best practices.
Last version of your view can be:
class ProfileDetailView(LoginRequiredMixin, DetailView):
model = Profile
def get_object(self):
return get_object_or_404(self.model, user=self.request.user)

There was a problem with the button not working

I am a student who wants to be good at Django. The button does not work. If you press the button in detail.html, I want to save the product in DB as if I purchased it. My goal is to get the buyer, date, and product code as written on views.py. However, even if you press the button now, you can't save it in DB. What's the problem?
model.py
class Join(models.Model):
join_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
part_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.join_code)
class Meta:
ordering = ['join_code']
Join/views
from datetime import timezone
from django.shortcuts import render
from zeronine.models import *
def join_detail(request):
product = Product.objects.all()
if request.method == "POST":
join = Join()
join.product_code = product
join.username = request.user
join.part_date = timezone.now()
join.save()
return render(request, 'zeronine/detail.html', {'product': product})
detail.html
{% extends 'base.html' %}
{% block title %} 상품 상세보기 {% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-4">
<img src="{{product.image.url}}" width="190%" style="margin-top: 35px;">
</div>
<div class="text-center col" style="margin-top:150px; margin-left:200px;">
<b><h4 class="content" style="margin-bottom: -5px;"><b>{{product.name}}</b></h4></b>
<br>
<div>
<!-- <span>주최자 : <b>{{ product.username }}</b></span><br>-->
<span style="color: #111111">모집기간 : <b>{{ product.start_date }} ~ {{ product.due_date }}</b></span>
</div>
<hr style="margin-top: 30px; margin-bottom: 30px;">
<p><span class="badge badge-dark">가격</span>
{% load humanize %}
{% for designated in designated_object %}
{% if designated.product_code.product_code == product.product_code %}
{{designated.price | floatformat:'0' | intcomma }}원
{% endif %}
{% endfor %}</p>
<span class="badge badge-dark">목표금액</span> {{ product.target_price | floatformat:'0' | intcomma }}원 <br><br>
<p class="badge badge-dark">공동구매 취지
{{product.benefit|linebreaks}}</p>
<p class="badge badge-dark">상세설명
{{product.detail|linebreaks}}</p>
<br>
<form action="" method="post">
{% csrf_token %}
<a onclick="alert('{{ product.name }} 공동구매 참여가 완료되었습니다.');" style="cursor:pointer;">
<form method="POST" action ="{% url 'zeronine:join_detail' %}">
{% csrf_token %}
<div class="form-group">
<button type="submit" action="{% url 'zeronine:join_detail' %}" class="btn btn-primary" style="float: right; background: #637B46; border: white">업로드</button>
</div>
</form>
</a>
</form>
</div>
</div>
</div>
{% endblock %}
I am not sure but you have a form inside a form in your template. maybe that is causing the problem.
also
in the POST section. it is best practice to use
join = Join.objects.create(product_code=product, ....)```

how can I access userprofile from another user?

I need some help when I create a user and user profile accordingly and when I try to access to any user by another user the request turns me on the request I work on not the real user, although, I'm using the slug to specify what the user I click on it maybe I can not explain what happens to me exactly for more explanation, please click on that video to show what I mean: https://www.youtube.com/watch?v=MzSo0ay2_Xk&feature=youtu.be
accounts app
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.template.defaultfilters import slugify
CHOICE = [('male', 'male'), ('female', 'female')]
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100, unique=True, blank=True)
overview = models.TextField(editable=True, blank=True, default='You have no an Overview yet')
city = models.CharField(max_length=20, blank=False)
phone = models.IntegerField(default=0, blank=True)
sex = models.CharField(max_length=10, default='male', choices=CHOICE)
skill = models.CharField(max_length=100, default='You have no skills yet')
logo = models.ImageField(upload_to='images/', default='images/default-logo.jpg', blank=True)
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super().save(*args, **kwargs)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
view.py
class ViewProfile(UpdateView):
queryset = UserProfile.objects.all()
template_name = 'accounts/profile.html'
form_class = UpdateInfoForm
slug_field = 'slug'
slug_url_kwarg = 'user_slug'
def get_success_url(self):
return reverse_lazy('accounts:view_profile', kwargs={'user_slug': self.request.user.userprofile.slug})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user_prof = UserProfile.objects.get(user=self.request.user)
context['user_prof'] = user_prof
context['get_favourite'] = User.objects.get(username=self.request.user.username).favorite.all()
return context
def form_valid(self, form):
form.instance.user_slug = self.request.user.userprofile.slug
self.object = form.save()
return super().form_valid(form)
profile.html
{% extends 'base.html' %}
{% block title %} {{ user.first_name }} {{ user.last_name }} Profile {% endblock %}
{% block body %}
<!-- User Profile Section -->
{% if user.is_authenticated %}
<div class="profile">
<div class="container-fluid">
<div class="col-md-1">
<div class="thumbnail">
<div class="row">
<div class="col-xs-12">
<!-- Profile View Section -->
<div class="logo-image text-center">
{% if user.userprofile.logo %}
<div class="my-image">
{% if request.user.username == user.userprofile.slug %}
<a href="{% url 'accounts:user_image' user.userprofile.slug %}">
<img class="img-responsive" src="{{ user.userprofile.logo.url }}">
</a>
<span>
<a href="{% url 'accounts:add_avatar' user.userprofile.slug %}" class="fa fa-camera fa-1x text-center">
<p>Upload Image</p>
</a>
</span>
{% endif %}
</div>
{% else %}
{% load static %}
<div class="my-image">
<img class="img-responsive img-thumbnail" src="{% static 'index/images/default-logo.jpg' %}">
<span>
<a href="{% url 'accounts:add_avatar' user.userprofile.slug %}" class="fa fa-camera fa-1x text-center">
<p>Upload Image</p>
</a>
</span>
</div>
{% endif %}
<h4>{{ user.first_name }} {{ user.last_name }}</h4>
</div>
</div>
<div class="col-xs-12">
<div class="caption">
<ul class="nav nav-pills nav-stacked">
<li role="presentation" class="active">Overview</li>
<li role="presentation" class="">Personal Information</li>
<li role="presentation" class="">Skills</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Information Sections -->
<div class="col-md-8 col-md-offset-3 information">
<div class="overview show" id="overview">
<h2 class="line">Overview</h2>
<p class="lead">{{ user.userprofile.overview }}</p>
<a data-placement="bottom" title="update overview" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".overview_info"></a>
</div>
<div class="personal-info" id="personal-information">
<h2 class="line">Personal Information</h2>
<p class="lead">City: {{ user.userprofile.city }}</p>
<p class="lead">Phone Number: 0{{ user.userprofile.phone }}</p>
<p class="lead">Sex: {{ user.userprofile.sex }}</p>
<a data-placement="bottom" title="update personal information" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".personal_info"></a>
</div>
<div class="skill" id="my-skills">
<h2 class="line">Skills:</h2>
<p class="lead">{{ user.userprofile.skill }}</p>
<a data-placement="bottom" title="update skills" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".skills"></a>
</div>
</div>
<!-- get all questions -->
{% if user_prof.userasking_set.all %}
<div class="col-md-8 col-md-offset-3 user_questions">
<h2 class="line">All Questions You Asked</h2>
{% for questions in user_prof.userasking_set.all %}
<p>{{ questions.title }}</p>
{% endfor %}
</div>
{% endif %}
<!-- get favourites -->
{% if get_favourite %}
<div class="col-md-8 col-md-offset-3 user_questions">
<h2 class="line">Favourites</h2>
{% for fav in get_favourite %}
<p>{{ fav.title }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% include 'accounts/information_form.html' %}
</div>
{% include 'base_footer.html' %}
{% endif %}
{% endblock %}
self.request.user refers to the currently logged in user. That is why you are getting the same result for all users.
To get what you want, you need to make the following change in your views:
user_prof = UserProfile.objects.get(pk=self.kwargs['pk'])
But also, I'm not sure why you are using an UpdateView when you simply want to display objects? You should use TemplateView instead.

How to create a search function on a class-based list view?

I am trying to create a search function based on the title of my posts. Right now I am trying to implement this search using a filter but the list view is not rendering. I am unsure if I should implement a URL for my search function.
This is my model:
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg', upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
feedback = models.ManyToManyField(Feedback)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk' : self.pk})
This is my class-based list view:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self):
object_list = super(PostListView, self).get_queryset()
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = title)
return object_list
This is my search bar:
<div id="search">
<form method='GET' action=''>
<input type="text" name='q' placeholder="">
<button id='search_holder'>
<img src="/static/store/search_icon.gif" id="search_icon">
</button>
</form>
</div>
This is my html that is rendering the posts:
{% extends "store/base.html" %}
{% block content %}
{% include "store/home_ext.html" %}
<div style="padding-top: 20px;" id="main" >
<section class="text-center mb-4">
<div class="row" id="random">
{% for post in posts %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="subscription" style="display: none;">
{% if not subs %}
<h2>You have not subscribed to any course :/</h2>
{% endif %}
{% for post in subs %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="content" style="display: none;">
{% if not mine %}
<h2>You have not published anything :/</h2>
{% endif %}
{% for post in mine %}
{% include "store/card.html" %}
{% endfor %}
</div>
</section>
{% include "store/pagination.html" %}
</div>
{% endblock content %}
This is my card.html:
{% load extra_filter %}
<div class="col-lg-3 col-md-6 mb-4">
<div id="course_card">
<div class="view overlay">
<img style="margin-left: -10px;" src="{{ post.image.url }}" alt="">
</div>
<div>
<div>
<strong>
{% if user.is_authenticated %}
<a class="title" href="{% url 'post-detail' post.id %}" >
{% else %}
<a class="title" href="{% url 'login' %}" >
{% endif %}
{% if post.title|length < 30 %}
<span>{{ post.title }}</span>
{% else %}
<span>{{ post.title|cut:27 }}</span>
{% endif %}
<span style="background-color: rgb(253, 98, 98);" class="badge badge-pill danger-color">NEW
</span>
</a>
</strong>
</div>
<div class="star-ratings-css">
<div class="star-ratings-css-top" style="width: {{ post.feedback|calc_rating }}%"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
<div class="star-ratings-css-bottom"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
</div>
<a href="{% url 'user-posts' post.author.username %}" class="author">
by {{ post.author }}
</a>
<div>
<strong style="text-align: right;" class="price">S${{ post.price }}
</strong>
</div>
<small class="date">
{{ post.date_posted|date:'d F y'}}
</small>
</div>
</div>
</div>
As Nalin Dobhal mentioned in comments, context_object_name should be posts not post. Because in template, you are iterating through posts context variable. Also, when using search functionality, the implementation should be like this:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # /_.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self, *args, **kwargs):
object_list = super(PostListView, self).get_queryset(*args, **kwargs)
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = search)
return object_list
Because you are sending the search query through URL querystring(ie: url will look like /posts/?q=title in browser). I am using request.GET.get('q') to fetch those query string values, and use it to filter the queryset.

Displaying ManyToManyField in django template

I've been trying to display the exact values of model with ManyToMany relation but I just couldn't, all what I've achevied is receiving QuerySet
<QuerySet [<Stack: PHP>, <Stack: js>]>
by adding to template tags
{{ brand.technologies.all }}
But I would like to receive and display 2 fields, name and icon. I've tried with some loops like
{% for brand in brands %}
{% for technologies in brand.technologies.all %} {{ technologies.name }} {{ technologies.icon }} {% endfor %}
{% endfor %}
but it doesn't give any results. There is not problem with syntax because page is displaying and looks like this
image
models.py
STACK = (
('PHP', 'PHP'),
('js', 'JavaScript'),
...
)
STACK_ICONS = (
('/static/icons/stack/php.png', 'PHP'),
('/static/icons/stack/javascript.png', 'JavaScript'),
...
)
class Company(models.Model):
name = models.CharField(max_length=100, blank=False)
students = models.CharField(max_length=3, choices=STUDENTS)
type = models.CharField(max_length=15, choices=TYPES)
workers = models.PositiveIntegerField(validators=[MinValueValidator(1)])
city = models.CharField(max_length=15,choices=CITIES)
company_about = models.TextField(max_length=500, blank=False)
slug = models.SlugField(unique=True)
icon = models.ImageField(blank=True, null=True)
image = models.ImageField(blank=True, null=True)
logo = models.ImageField(blank=True, null=True)
technologies = models.ManyToManyField('Stack')
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Company, self).save(*args, **kwargs)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.name
# object stack relation manytomany with Company
class Stack(models.Model):
name = models.CharField(max_length=30, choices=STACK)
icon = models.CharField(max_length=80, choices=STACK_ICONS)
def __str__(self):
return self.name
views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
...
def comp_list(request):
f = CompanyFilter(request.GET, queryset=Company.objects.all())
return render(request, 'company/comp_list.html', {'filter': f})
def companies(request):
company = get_object_or_404(Company)
return render(request, 'company/comp_list.html', {'company': company})
def home(request):
return render(request, 'company/home.html')
def brands(request, slug):
brand = get_object_or_404(Company, slug=slug)
return render(request, 'company/comp_view.html', {'brand': brand})
def stacks(request):
stack = get_object_or_404(Stack)
return render(request, 'company/comp_view.html', {'stack': stack})
comp_view.html
{% extends 'company/base.html' %}
{% block content %}
<div class="row company-details">
<div class="col col-md-2"></div>
<div class="col col-md-8">
<input class="btn btn-success" type="button" value="Go Back" onclick="history.back(-1)" />
<div class="col col-md-12 company-bg" style="background-image: url('{{ brand.image.url }}'); background-repeat: no-repeat, repeat;">
</div>
<div class="bottom-overlay"></div>
<div class="company-description">
<div class="heading">
<div class="title">About us</div>
<div class="social-media">
Facebook
</div>
</div>
<div class="company-about">
{{ brand.company_about }}
</div>
</div>
<div class="company-stats">
<div class="company-logo-container">
<img class="company-logo" src="{{ brand.logo.url }}">
</div>
<div class="company-attributes">
<div class="field-group">
<div class="field">Type</div>
<div class="value">{{ brand.type }}</div>
</div>
<div class="field-group">
<div class="field">Company size</div>
<div class="value">{{ brand.workers }}+</div>
</div>
<div class="field-group">
<div class="field">Headquarters</div>
<div class="value">{{ brand.city }}</div>
</div>
<div class="field-group">
<div class="field">Open for students</div>
<div class="value">{{ brand.students }}</div>
</div>
</div>
<div class="technologies-section">
<p class="tech-heading">Technologies</p>
<div class="technologies-wrapper">
{{ brand.technologies.all }}
{% for brand in brands %}
{% for technologies in brand.technologies.all %} {{ technologies.name }} {% endfor %}
{% endfor %}
</div>
</div>
</div>
<div class="col col-md-2"></div>
</div>
{% endblock %}
I don't understand why you've suddenly added an outer loop through brands. You don't have anything called brands, and you're successfully accessing all the other data via brand. Just continue to do so, and drop the outer loop.
<div class="technologies-wrapper">
{% for technologies in brand.technologies.all %} {{ technologies.name }} {% endfor %}
</div>