get_absolute_url not making any effect - python

I only used this in my template. I am following a tutorial. In tutorial video is working but I couldn't make it work. Here is my template code:
<i> {% for object in object_list %}
<div class="media">
<div class="media-left">
<a href="#">
{% if object.img %} <img class="media-object" src="..." alt="...">
{% endif %}
</a>
</div>
<div class="media-body">
{{ object.content }}<br/>
via {{ object.user }} | {{ object.timestamp|timesince }} ago |
<a href='{{ object.get_absolute_url }}'>View</a>
</div>
</div>
<hr/> </i>
My views.py
<i>
Create your views here.
class TweetCreateView(FormUserNeededMixin, CreateView):
form_class = TweetModelForm
template_name = 'tweets/create_view.html'
class TweetUpdateView(LoginRequiredMixin, UserOwnerMixin, UpdateView):
form_class = TweetModelForm
queryset = Tweet.objects.all()
template_name = 'tweets/update_view.html'
success_url = '/tweets/'
class TweetDeleteView(LoginRequiredMixin, DeleteView):
model = Tweet
template_name = 'tweets/delete_confirm.html'
success_url = reverse_lazy('tweets:home')
class TweetDetailView(DetailView):
template_name = "tweets/detail_view.html"
queryset = Tweet.objects.all()
def get_object(self):
print(self.kwargs)
pk = self.kwargs.get("pk")
print(pk)
return Tweet.objects.get(id=pk)
class TweetListView(ListView):
template_name = "tweets/tweets_list.html"
def get_queryset(self, *args, **kwargs):
qs = Tweet.objects.all()
print(self.request.GET)
query = self.request.GET.get("q", None)
if query is not None:
qs = qs.filter(Q(content=query))
return qs
def get_context_data(self, *args, **kwargs):
context = super(TweetListView, self).get_context_data(*args, **kwargs)
context['create_form'] = TweetModelForm()
context['create_url'] = reverse_lazy('tweets:create')
return context
</i>
my models.py
<i>
class Tweet(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, )
content = models.CharField(max_length=140, validators=[ validate_content ])
updated = models.DateField(auto_now=True, )
timestamp = models.DateField(auto_now_add=True, )
def __str__(self):
return str(self.content)
</i>

You have to add methode get_absolute_url to your models, it's should look like that :
def get_absolute_url(self):
from django.urls import reverse
return reverse('tweets:detail', kwargs={
'pk': self.pk
})

Related

My article doesn't display in article_details

I want to show my articles but
My article doesn't display on article_details.html
This is what my site looks like. You can see only my article's title works.
My models.py:
class Article(models.Model):
title = models.CharField(max_length=50, verbose_name="Title")
mini_description = models.TextField(max_length=100, default='', verbose_name='Mini_description')
content = models.TextField(blank=True, verbose_name="Content")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of add")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Update date")
photo = models.ImageField(upload_to='photos/', verbose_name="Photo")
is_published = models.BooleanField(default=True, verbose_name="Is published")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="Category")
def get_absolute_url(self):
return reverse("article_details", kwargs={'pk': self.pk})
def __str__(self):
return self.title
def __repr__(self):
return f"Article(pk={self.pk}, title='{self.title}')"
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"
ordering = ['-created_at']
My views.py:
class ArticleListByCategory(ListView):
model = Article
context_object_name = 'articles'
template_name = 'blog/details.html'
def get_queryset(self):
sort_filed = self.request.GET.get('sorter')
articles = Article.objects.filter(category_id=self.kwargs['pk'])
if sort_filed:
articles = articles.order_by(sort_filed)
return articles
class ArticleDetails(ArticleListByCategory):
model = Article
context_object_name = 'article'
template_name = 'blog/article_details.html'
def get_queryset(self):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
def get_context_data(self, **kwargs):
context = super().get_context_data()
article = Article.objects.get(pk=self.kwargs['pk'])
context['title'] = f"Article: {article.title}"
return context
My article_details.html:
{% extends "base.html" %}
{% load static %}
{% block style %}
<link href="{% static 'blog/css/main.css' %}" rel="stylesheet">
{% endblock style %}
{% block title %}
{{ title }}
{% endblock %}
{% block main %}
<section class="articles" id="articles">
<div class="card_details">
<h1>{{ article.title }}</h1>
<p><em>{{ article.mini_description }}
</em>
</p>
<img src="">
<div class="description">
<p>
{{ article.content }}
</p>
</div>
<div class="card-footer text-muted">
{{ article.created_at| timesince }} ago
</div>
</div>
</section>
{% endblock main %}
I don't know why my article doesn't display.
What I'd suggest here is using the Django Generic View called DetailView. For example, you could do the following:
from django.views.generic import DetailView
class ArticleDetails(DetailView):
context_object_name = 'article'
template_name = 'blog/article_details.html'
# Using the get_object method here, not get_queryset.
def get_object(self, queryset=None):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
Ideally, that should work.

How do i show a list of object in Django DetailView

I'm still learning Django, using Class based view, i have created a ProductDetailView and have a ProductListView.
Everything working perfect, but i want to add on my product_detail page, a list of products, after client viewed a product_detail page may also be interested by related product or what they may want. enter image description here
**my model.py**
class Product(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(null=False, unique=True)
featured = models.ImageField(upload_to='product_images')
price = models.IntegerField(default=0)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
available_colours = models.ManyToManyField(ColourVariation, blank=True)
available_sizes = models.ManyToManyField(SizeVariation)
primary_category = models.ForeignKey(
Category, related_name='primary_products', blank=True, null=True,
on_delete=models.CASCADE)
secondary_categories = models.ManyToManyField(Category, blank=True)
stock = models.IntegerField(default=0)
def __str__(self):
return self.title
ProductListView:
class ProductListView(generic.ListView):
template_name = 'cart/product_list.html'
def get_queryset(self):
qs = Product.objects.all()
category = self.request.GET.get('category', None)
if category:
qs = qs.filter(Q(primary_category__name=category) |
Q(secondary_categories__name=category)).distinct()
return qs
def get_context_data(self, **kwargs):
context = super(ProductListView, self).get_context_data(**kwargs)
context.update({
"categories": Category.objects.values("name")
})
return context
**ProductDetailView:**
class ProductDetailView(generic.FormView):
template_name = 'cart/product_detail.html'
form_class = AddToCartForm
def get_object(self):
return get_object_or_404(Product, slug=self.kwargs["slug"])
def get_success_url(self):
return reverse("cart:summary")
def get_form_kwargs(self):
kwargs = super(ProductDetailView, self).get_form_kwargs()
kwargs["product_id"] = self.get_object().id
return kwargs
def form_valid(self, form):
order = get_or_set_order_session(self.request)
product = self.get_object()
item_filter = order.items.filter(
product=product,
colour=form.cleaned_data['colour'],
size=form.cleaned_data['size'],
)
if item_filter.exists():
item = item_filter.first()
item.quantity += int(form.cleaned_data['quantity'])
item.save()
else:
new_item = form.save(commit=False)
new_item.product = product
new_item.order = order
new_item.save()
return super(ProductDetailView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(ProductDetailView, self).get_context_data(**kwargs)
context['product'] = self.get_object()
return context
I have tried the below code which work fine on my product_list but don't work on my
product_detail page
I added get_context_data in to my view and this html, but it doesn't work.
**view.py**
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = Product.objects.all()
return context
**product_detail page**
{% for product in object_list %}
<div class="col-6 col-lg-3 text-center">
<div class="product">
<figure class="product-image">
<a href="{{ product.get_absolute_url }}">
<img src="{{ product.featured.url }}" alt="Image">
</a>
</figure>
<a href="{{ product.get_absolute_url }}">
<p class="mb-0">{{ product.title }}</p>
<div class="product-rating mb-0" id="product-rating">
<i class="icon-star{% if product.avaregereview < 1%}-o empty{% endif%}"></i>
<i class="icon-star{% if product.avaregereview < 2%}-o empty{% endif%}"></i>
<i class="icon-star{% if product.avaregereview < 3%}-o empty{% endif%}"></i>
<i class="icon-star{% if product.avaregereview < 4%}-o empty{% endif%}"></i>
<i class="icon-star{% if product.avaregereview < 5%}-o empty{% endif%}"></i>
</div>
<span class="text-muted text-center">${{ product.get_price }}
<span class="">/</span>
<span class="text-danger">{% trans "Add to Cart" %}</span>
</span></a>
</div>
</div>
{% endfor %}

Automatically join the user who created the group

I have a project called social clone project in this project you can only post if you are in a group. What i want to happen is if the user created a group the user should automatically in the group, in this case if i created a group i still need to join the group to join my own group. I tried to search this on google but i get no result and i hope someone will help me and btw i'm just new here in programming and i'm currently learning django.
models.py
##########################
## GROUPS VIEWS.PY FILE ##
##########################
from django.contrib.auth import get_user_model
from django import template
from django.db import models
from django.utils.text import slugify
from misaka import html
from django.urls import reverse
User = get_user_model()
register = template.Library()
class Group(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(allow_unicode=True, unique=True)
description = models.TextField(blank=True, default="")
description_html = models.TextField(editable=False, blank=True, default="")
members = models.ManyToManyField(User, through='GroupMember')
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
self.description_html = html(self.description)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse('groups:single', kwargs={'slug': self.slug})
class Meta:
ordering = ['name']
class GroupMember(models.Model):
user = models.ForeignKey(User, related_name='user_groups', on_delete=models.CASCADE)
group = models.ForeignKey(Group, related_name='memberships', on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class Meta:
unique_together = ('user', 'group')
views.py
##########################
## GROUPS VIEWS.PY FILE ##
##########################
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import generic
from groups.models import Group, GroupMember
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.db import IntegrityError
from django.contrib import messages
class CreateGroup(LoginRequiredMixin, generic.CreateView):
model = Group
fields = ('name', 'description')
class SingleGroup(generic.DetailView):
model = Group
class ListGroups(generic.ListView):
model = Group
class JoinGroup(LoginRequiredMixin, generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('groups:single', kwargs={'slug': self.kwargs.get('slug')})
def get(self, request, *args, **kwargs):
group = get_object_or_404(Group, slug=self.kwargs.get('slug'))
try:
GroupMember.objects.create(user=self.request.user, group=group)
except IntegrityError:
messages.warning(self.request, (f"Warning, already a group member of {group.name} group."))
else:
messages.success(self.request, (f"You are now a member of {group.name} Group."))
return super().get(request, *args, **kwargs)
class LeaveGroup(LoginRequiredMixin, generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('groups:single', kwargs={'slug': self.kwargs.get('slug')})
def get(self, request, *args, **kwargs):
try:
membership = GroupMember.objects.filter(
user=self.request.user,
group__slug=self.kwargs.get('slug')
).get()
except GroupMember.DoesNotExist:
messages.warning(self.request, ("You can't leave this group because you aren't in it!"))
else:
membership.delete()
messages.success(self.request, ("You have successfully left this group."))
return super().get(request, *args, **kwargs)
group_form.html
{% extends 'groups/group_base.html' %}
{% load bootstrap4 %}
{% block group_content %}
<div class="container">
<h4>Create New Group</h4>
<form id="groupForm" action="{% url 'groups:create' %}" method="POST">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-large btn-primary">Create</button>
{% endbuttons %}
</form>
</div>
{% endblock %}
group_detail.html
{% extends 'groups/group_base.html' %}
{% block pregroup %}
<div class="container">
<h1>{{ group.name }}</h1>
<h2>Member Count: {{ group.members.count }}</h2>
<div class="content">
{% if user in group.members.all %}
<a class="btn btn-lg btn-warning" href="{% url 'groups:leave' slug=group.slug %}"><span class="fa fa-times-circle-o"></span>Leave</a>
{% else %}
<a class="btn btn-lg btn-warning" href="{% url 'groups:join' slug=group.slug %}"><span class="fa fa-check-circle-o"></span>Join</a>
{% endif %}
</div>
</div>
{% endblock %}
{% block group_content %}
<div class="col-md-8">
{% if group.posts.count == 0 %}
<h2>No Post In This Group Yet!</h2>
{% else %}
{% for post in group.posts.all %}
{% include 'posts/_post.html' %}
{% endfor %}
{% endif %}
</div>
{% endblock %}
Override the form_valid method on your CreateGroup view, here you can perform some additional logic after the object has been saved
class CreateGroup(LoginRequiredMixin, generic.CreateView):
model = Group
fields = ('name', 'description')
def form_valid(self, form):
result = super().form_valid(form)
GroupMember.objects.create(user=self.request.user, group=self.object)
return result
ccbv.co.uk is fantastic for inspecting the available methods there are to override for the built-in class based views

django combine multiple ListView using get_query and search form

in my project, I have three models
models.py
class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True, null=True, blank=True)
parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='children')
class Tag(models.Model):
tag = models.CharField(max_length=75, verbose_name='Tag')
slug = models.SlugField(null=True)
class Post(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(max_length=150, null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
tags = models.ManyToManyField(Tag, related_name='tags', blank=True)
and I created search filter view in views.py
def is_valid_queryparam(param):
return param != '' and param is not None
class SearchPepsiView(ListView):
template_name = "blog/NewSearch.html"
model = Post
paginate_by = 10
def get_queryset(self):
return Post.objects.filter(category__slug=self.kwargs['slug'])
def get_context_data(self, *args, **kwargs):
context = super(SearchPepsiView, self).get_context_data(*args, **kwargs)
context['category'] = Post.objects.filter(category__slug=self.kwargs['category'])
return context
def get(self, request, *args, **kwargs):
request = self.request
qs = Post.objects.all()
categories = Category.objects.filter(parent=None).order_by('name')
PostOrAuthor_query = request.GET.get('PostOrAuthor')
SearchCategory_query = request.GET.get('SearchCategory')
if is_valid_queryparam(PostOrAuthor_query):
qs = qs.filter(Q(title__icontains=PostOrAuthor_query) |
Q(content__icontains=PostOrAuthor_query) |
Q(author__username__icontains=PostOrAuthor_query)).distinct()
if is_valid_queryparam(SearchCategory_query) and SearchCategory_query != 'Choose...':
qs = qs.filter(category__name=SearchCategory_query)
count = qs.count() or 0
return render(request, self.template_name, {
'queryset': qs,
'categories': categories,
'count': count,
})
and I created Post Per Category View in views.py
class PostPerCategoryCBV(ListView):
model = Post
template_name = 'blog/Category_Projects.html'
def get_queryset(self):
self.category = Category.objects.get(slug=self.kwargs['slug'])
return Post.objects.filter(category=self.category)
def get_context_data(self, **kwargs):
context = super(PostPerCategoryCBV, self).get_context_data(**kwargs)
context['category'] = self.category
return context
and I created Post Per Tag View in views.py
class PostPerTagCBV(ListView):
model = Post
template_name = 'blog/tag_projects.html'
def get_queryset(self):
qs = super().get_queryset()
qs = qs.filter(tags__slug=self.kwargs['slug'])
return qs
and in templates, I created NewSearch.html
<form class="col-12 mt-5 mb-5">
<div class="form-group">
<label for="formGroupExampleInput">Post or Author</label>
<input type="search" name="PostOrAuthor" class="form-control" id="inputAddress" placeholder="Post or Author">
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label for="SearchCategory">Category</label>
<select id="SearchCategory" name="SearchCategory" class="form-control">
<option selected>Choose...</option>
{% for cat in categories %}
<option value="{{ cat.name }}">{{ cat.name }}</option>
{% endfor %}
</select>
</div>
</div>
<button type="submit" class="btn btn-primary col-12">Search</button>
</form>
</div>
<div class="row">
<p>You have<b> {{ count }} </b>search results </p>
</div>
{% if category %}
<div class="row">
{% for post in category %}
{% include 'blog/Post_Loop.html' %}
{% endfor %}
</div>
{% else %}
<div class="row">
{% for post in queryset %}
{% include 'blog/Post_Loop.html' %}
{% endfor %}
</div>
{% endif %}
</div>
and Here is my URLs.py
path('post_list/', PostListCBV.as_view(), name='list-post'),
path("search-pepsi/", SearchPepsiView.as_view(), name="search-pepsi"),
path('tags_projects/<str:slug>/', PostPerTagCBV.as_view(), name='tag-posts'),
path('category_posts/<str:slug>/', SearchPepsiView.as_view(), name='category-posts'),
My success:
When all search fields are empty .. it list all posts.
when entering any search query .. it backs with the search result.
my problem is:
I believe that there are someway I can combine ListView of Post_Per_Category and Post_Per_Tag with Search View (in ONE View and one template) .. so I created def get_queryset(self): to use it but it didn't worked.
Anybody can help please ...
Thanks in-advance

Django: cannot redirect to UpdateView after item is deleted

I'm creating a view just for deleting ListItems that correspond to a List objects, through a ForeignKey.
I can successfully delete the ListItem, but I cannot redirect to the original template.
def full_remove_listitem(request, listitem_id):
list_item = ListItem.objects.get(id=listitem_id)
list_item.delete()
lista_id = list_item.lista.id
return redirect('lists:list_details lista_id')
I get:
NoReverseMatch at /listas/borrar-producto-de-lista/29/
Reverse for 'list_details lista_id' not found. 'list_details lista_id' is not a valid view function or pattern name.
I've also tried:
return reverse('lists:list_details', kwargs={'lista_id': lista_id})
But I get:
AttributeError at /listas/borrar-producto-de-lista/30/ 'str' object
has no attribute 'get'
Urls.py:
app_name = "lists"
urlpatterns = [
path('', views.ListFormView.as_view(), name='my_lists'),
path('agregar-producto/', views.add_product_to_list, name='add_product_to_list'),
path('mis-listas/', views.update_lists_count, name='update_lists_count'),
path('lista-detalles/<int:lista_id>/', views.ListDetailsFormView.as_view(), name='list_details'),
path('escuelas-csv/', views.schools_upload, name="schools_upload"),
path('borrar-producto-de-lista/<int:listitem_id>/', views.full_remove_listitem, name='full_remove_listitem'),
path('borrar-lista/<int:lista_id>/', views.full_remove_list, name='full_remove_list'),
path('borrar-escuela/<int:school_id>/', views.full_remove_school, name='full_remove_school'),
]
HTML:
<div class="row">
{% for list_item in list_items %}
{% if forloop.counter0|divisibleby:3 and not forloop.first %}<div class="w-100"></div>{% endif %}
<div class="card margin-right3" style="width: 14rem;">
<div class="card-body">
<h5 class="card-title">{{ list_item.product.short_name }}</h5>
<p class="card-title">$ {{ list_item.product.price }}</p>
<p class="card-text">{{ list_item.description }}</p>
<a href="{% url 'lists:full_remove_listitem' list_item.id %}" class="custom_icon"><i
class="fas fa-trash-alt custom_icon"></i></a>
</div>
</div>
{% endfor %}
views.py: View where I want to redirect:
class ListDetailsFormView(LoginRequiredMixin, UpdateView):
model = List
form_class = ListForm
context_object_name = 'lista'
pk_url_kwarg = 'lista_id'
template_name = "scolarte/listas/lista-detalles.html"
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
list_items = ListItem.objects.filter(lista=self.object)
context['list_items'] = list_items
list_total = 0
for list_item in list_items:
list_total += Decimal(list_item.sub_total())
context['list_total'] = list_total
return context
def form_valid(self, form):
#form.instance.name = self.request.name
return super().form_valid(form)
def get_success_url(self):
return reverse('lists:list_details', kwargs={'lista_id': self.object.pk})
models.py:
class ListItem(models.Model):
lista = models.ForeignKey(List, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
comment = models.CharField(max_length=100, blank=True, null=True, default='')
uploaded_at = models.DateTimeField(auto_now_add=True)
step_two_complete = models.BooleanField(default=False)
def sub_total(self):
return int(self.product.price)
If you take a look at the second example in the redirect() documentation you'll see that the first argument should be the view name then the id can be passed as a keyword argument.
def full_remove_listitem(request, listitem_id):
list_item = ListItem.objects.get(id=listitem_id)
list_item.delete()
lista_id = list_item.lista.id
return redirect('lists:list_details', lista_id=lista_id)

Categories