django show pagination links First , Previous , Next , Last on edit page that uses UpdateView or DetailView - django

I am using django 3.2 along with datatables and bootstrap 5. it shows pagination correctly using datatables. I want to show Links/buttons like First, previous,Next and Last on edit productstatus form using datatables pagination or django pagination django.core.paginator whose details as shown below
class ProductStatus(models.Model):
ProductID = models.CharField(max_length=512, verbose_name="ProductID", null=False, blank=False)
Description = models.CharField(max_length=512, verbose_name="Description", null=True, blank=True)
CreateDate = models.DateTimeField(verbose_name=_("CreateDate"), blank=True)
modificationtime = models.DateTimeField(verbose_name="modificationtime", null=True, blank=True, )
...
def __str__(self):
return self.ProductID
def get_absolute_url(self):
return reverse('productdetail', args=[str(self.id)])
urls.py has entry as shown below
path('editproduct/int:pk/edit/', EditProductView.as_view(), name='editproduct'),
views.py contains following code
class EditProductView(LoginRequiredMixin, UpdateView):
model = ProductStatus
template_name = 'editproduct.html'
form_class = EditProductStatusForm
login_url = 'login'
def form_valid(self, form):
editedproduct = form.save(commit=False)
editedproduct.modificationtime = timezone.now()
editedproduct.save()
# self.object = editedproduct
return super().form_valid(form)
Forms.py contains
class EditProductStatusForm(forms.ModelForm):
class Meta:
model = ProductStatus
editproduct.html looks as shown below
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<br>
<!-- show 4 links in bootstrap navigation bar -->
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid ">
<div class="nav navbar-left">
<ul class="nav navbar-nav">
<li><a class="btn btn-info btn-sm" style="padding-left:0px;margin-left:10px" href="#" role="button">« First</a></li>
<li><a class="btn btn-info btn-sm" style="padding-left:0px;margin-left:10px" href="#" role="button">‹ Previous</a></li>
</ul>
</div>
<div class="nav navbar-right">
<ul class="nav navbar-nav">
<li> <a class="btn btn-info btn-sm" style="padding-left:0px;margin-left:10px" href="#" role="button">Next ›</a></li>
<li> <a class="btn btn-info btn-sm" style="padding-left:0px;margin-left:10px" href="#" role="button">Last »</a></li>
</ul>
</div>
</div>
</nav>
<h3 class="text-center">Change Product Status </h3>
<form class="form-inline" role="form">
<div class="row">
<div class="col">
<div class="input-group mb-3">
<span class="input-group-text" style="background-color: #ffffff" id="labelFor-Product ID">Product ID </span>
<input type="text" style="background-color: #ffffff" class="form-control" value="{{ object.ProductID }}" readonly>
</div>
</div>
</form>
<form method="post">
{% csrf_token %}
<div class="row">
<div class="col-6">
{{ form.Description| as_crispy_field }}
</div>
</div>
<br>
<button type="submit" class="btn btn-success">Save</button>
</form>
{% endblock content %}
editproduct url is invoked from other datatables using list page as . this page allows sorting by click on table header
I need to show pagination on editproduct page with 4 links/buttons First,Previous,Next and Last or datatables like pagination so that user dont have go back to product list page and then click on edit icon to open editproduct status page and user can go to first product, Previous product, next product or last product from edit product status page itself.
I am aware of datatables pagination that requires passing productstatus_list and using table but not sure how to use datatables pagination or django.core.paginator on this editproduct status page or on product details page that uses DetailView where only product id is passed and available as shown above. what change/update is needed in above code to show desired pagination on the edit productstatus page.

Related

DJango, the preivous post or the next post according to that category list

I am studying to develope a blog website using DJango's generic view class.
I categorized blogs into categories.
If you select a blog from the full list and go to the detail page, you have implemented the ability to go to the previous post and the next post using "previous()" and "next()" in that post.
I want to select a blog from a category list and move it to the preivous post or the next post according to that category list, but I don't know how.
What can I do?
models.py
class Post(models.Model):
..........
def prev(self):
return self.get_previous_by_created_at()
def next(self):
return self.get_next_by_created_at()
views.py
class PostListByCategory(PostList):
def get_queryset(self):
slug = self.kwargs['slug']
if slug == 'no_category':
category = None
else:
category = Category.objects.get(slug=slug)
return Post.objects.filter(category=category).order_by('-pk')
def get_context_data(self, **kwargs):
context = super(PostListByCategory, self).get_context_data()
slug = self.kwargs['slug']
if slug == 'no_category':
category = 'None'
else:
category = Category.objects.get(slug=slug)
context['category'] = category
return context
post_detail.html
..............
<div class="row row-cols-auto">
{% if object.next %}
<div class="col">
<a href="{% url 'tube_detail' object.next.pk %}" class="btn btn-sm pt-1 pb-1 bg-light" title="Prev">
<i class="bi bi-caret-left-fill" style="color:#dd3535"></i>
</a>
</div>
{% endif %}
<div class="col">
<a href="{% url 'tube_list' %}{% if request.GET.category %}category/{{ request.GET.category}}{% endif %}" class="btn btn-sm pt-1 pb-1 bg-light" title="LIST">
<i class="bi bi-list" style="color:#dd3535"></i>
</a>
</div>
{% if object.prev %}
<div class="col">
<a href="{% url 'tube_detail' object.prev.pk %}" class="btn btn-sm pt-1 pb-1 bg-light" title="Next">
<i class="bi bi-caret-right-fill" style="color:#dd3535"></i>
</a>
</div>
{% endif %}
</div>
''''''''''''

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)

Bootstrap Modal submit button not working with DeleteView in Django 2.2

I am learning Django 2.2 and using a little bit of Bootstrap 4 to help with the front end. I have a Model created which stores some user information like first name and last name. I have created a DeleteView class which is supposed to delete entries from the database using the ID. Everything works fine as is. But if I try to implement the DeleteView class using a Bootstrap modal window, nothing seems to happen even if I click the submit button. I am not sure what I am doing wrong. I read in another thread here in Stackoverflow that we need to include the button inside a form which I have done too. But it still doesn't delete the entry. Below is all the code required.
Note - I have placed the Delete button inside the contacts_view.html file. The contacts_delete.html file is exactly the same. My idea is to provide the user to not just view the details but also update or even delete the specific entry. When I click on the Delete button, the modal pop up window appears. But when I click on the 'Confirm' button, the entry does not get deleted as required.
Please let me know how to proceed with this.
contacts_view.html / contacts_delete.html
{% extends 'base.html' %}
{% block content %}
<div class="container" style="width: 500px">
<div>
<div class="list-group" style="color: black">
<a class="list-group-item list-group-item-action my-1" style="background-color: wheat">
<div class="row">
<div class="col-4">
First Name
</div>
<div class="col-8">
{{ object.first_name }}
</div>
</div>
</a>
<a class="list-group-item list-group-item-action my-1" style="background-color: wheat">
<div class="row">
<div class="col-4">
last Name
</div>
<div class="col-8">
{{ object.last_name }}
</div>
</div>
</a>
</div>
</div>
<div class="border-top text-center my-4 pt-3">
<a class="btn btn-outline-danger ml-2" href="{% url 'contacts-delete' object.id %}" type="submit" data-toggle="modal" data-target="#myModal">Delete</a>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content" style="background-color: whitesmoke; color: dimgray">
<div class="modal-header">
<h4 class="modal-title">Delete Contact</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body text-left">
form
<p>Do you really want to delete {{ object.first_name }} {{ object.last_name }}?</p>
</div>
<div class="modal-footer">
<form method="POST" action="{% url 'contacts-delete' object.id %}">
{% csrf_token %}
<button class="btn btn-outline-warning ml-2" type="submit">Update</button>
<button type="button" class="btn btn-outline-danger" href="{% url 'contacts-delete' object.id %}" data-dismiss="modal">Delete</button>
</form>
<a type="button" class="btn btn-outline-secondary" href="{% url 'contacts-view' object.id %}" data-dismiss="modal">Cancel</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
views.py
from .models import Contact
from django.urls import reverse_lazy
from django.shortcuts import reverse
from django.views.generic import DetailView, DeleteView
class ContactDetailView(DetailView):
model = Contact
template_name = 'contacts/contacts_view.html'
class ContactDeleteView(DeleteView):
model = Contact
template_name = 'contacts_update.html'
success_url = reverse_lazy('contacts-browse')
models.py
from django.db import models
from django.contrib.auth.models import User
class Contact(models.Model):
added_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
first_name = models.CharField(max_length=35)
last_name = models.CharField(max_length=35, blank=True, default='')
def __str__(self):
return f"{self.first_name} {self.last_name}"
urls.py
from django.urls import path
from .views import ContactDetailView, ContactDeleteView
urlpatterns = [
path('view/<int:pk>/', ContactDetailView.as_view(), name='contacts-view'),
path('view/<int:pk>/delete/', ContactDeleteView.as_view(), name='contacts-delete'),
]

Django display content based on dropdown select

I am new in Django.
I want to display content based on dropdown selection.
In this example i want to show all the workshops data from the location selected in the dropdown.
Is it possible to achieve that without reloading the page? or if it must reload the page, is it possible to stay on current view after reloading the page?
Thank you.
I have tried to use post method and use onChange attribute on my forms.
It successfully reload the page but the workshops content is not shown, the dropdown selection go back to default '--- Choose your location ---' and the page go back to the top.
Below is the code of the forms
class LocationForm(forms.Form):
location = forms.ModelChoiceField(label='', queryset=Location.objects.all(), empty_label="--- Choose your location ---",
widget=forms.Select(
attrs={'id': 'ddlLocation', 'name':'ddlLocation', 'class':'selectpicker', 'data-live-search':'true', 'data-size':'5', 'onChange':'frLocation.submit();' }
)
)
Below is the code of the class
class HomeView2(ListView):
template_name = 'myapp/index.html'
def get(self, request):
form_location = LocationForm()
location_id = request.GET.get('location_id')
workshops = Workshop.objects.filter(location_id=location_id).order_by('workshop_name')
args = {'form_location':form_location, 'workshops':workshops}
return render(request, self.template_name, args)
def post(self,request):
form_location = LocationForm()
location_id = request.GET.get('location_id')
workshops = Workshop.objects.filter(location_id=location_id).order_by('workshop_name')
args = {'form_location':form_location, 'workshops':workshops}
return render(request, self.template_name, args)
and in index.html
<section class="page-section" id="services">
<div class="container">
<h2 class="text-center mt-0">At Your Service</h2>
<hr class="divider my-4">
<div class="row justify-content-center">
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5">
<i class="fas fa-4x fa-wrench text-primary mb-4"></i>
<h3 class="h4 mb-2">Select location</h3>
<form id="frLocation" name="frLocation" method="POST">
{% csrf_token %}
{{form_location}}
</form>
</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5">
<form id="frWorkshop">
{% for workshop in workshops %}
<p>Workshop: {{workshop.workshop_name}}</p>
{% endfor %}
</form>
</div>
</div>
</div>
</div>
</section>

How do you implement a Form in a ListView

I'm new to Django, I basically have a homepage which has a search bar that is being implement using a Django Form. Additionally, in the homepage I have bootstrap card whichis being used to display data from my model.
I'm using the def_get to render the form (since it's being used to query the DB). The form is very basic, it's just a CharField. However, when I use the def_get to render the Form in my class based view it now doesn't retrieve any of the data that goes into the bootstrap card which is causing the card to not display.
I've tried to render both the form and data in the card by using ModelFormMixin but it seems like this hasn't solved my issue yet, not sure whether this is the way to achieve this?
Forms.py
from django import forms
class SearchBarForm(forms.Form):
q = forms.CharField(label="", max_length=150, required=True)
Views.py
from django.views.generic import TemplateView
from django.views.generic.list import ListView
from property.models import Property
from pages.forms import SearchBarForm
from django.shortcuts import render
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get(self, request):
form = SearchBarForm()
return render(request, self.template_name, {'form': form})
Home.html
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<div class="container">
<!-- search bar -->
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8 custom-search-bar">
<form action="{% url 'property_for_rent' %}" method="get" id="search-form">
{{ form.as_p }}
</form>
</div>
<div class="col-xs-6-md-4 custom-search-bar-button">
<button type="submit" form="search-form" class="btn btn-light" value="For sale">For rent</button>
<button form="rent" type="submit" class="btn btn-light" value="For sale">For Sale</button>
</div>
</div>
<!-- search bar -->
<!-- property card -->
<div class="row">
{% for property in object_list|slice:"3" %}
<div class="col-lg-4 d-flex align-items-stretch custom-cards">
<div class="card" style="width: auto;">
<div class="card-img">
{% if property.image %}
<img class="card-img-top" src="{{property.image.url}}" alt="Card image cap"> {% endif %}
</div>
<div class="card-body">
<h5 class="card-title"> {{ property.location }} </h5>
<p class="card-text">{{ property.description }} </p>
<button type="button" class="btn btn-primary waves-effect waves-light" data-toggle="modal" data-target="#modal-{{ property.id }}">View</button>
</div>
<div class="card-footer">
<small class="text-muted">Last updated</small>
</div>
</div>
<!-- property card -->
<!-- Full Height Modal Right -->
<div class="modal fade right" id="modal-{{ property.id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<!-- Add class .modal-full-height and then add class .modal-right (or other classes from list above) to set a position to the modal -->
<div class="modal-dialog modal-full-height modal-right" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title w-100" id="myModalLabel">{{ property.location }}</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>{{ property.description }}</p>
<ul class="list-group z-depth-0">
<li class="list-group-item justify-content-between">
Bedrooms
<span class="badge badge-primary badge-pill">14</span>
</li>
<li class="list-group-item justify-content-between">
Price
<span class="badge badge-primary badge-pill">2</span>
</li>
<li class="list-group-item justify-content-between">
Location
<span class="badge badge-primary badge-pill">1</span>
</li>
<li class="list-group-item justify-content-between">
Property Type
<span class="badge badge-primary badge-pill">14</span>
</li>
</ul>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- Full Height Modal Right -->
</div>
{% endfor %}
</div>
</div>
{% endblock %}
What I want to achieve is to both display the search bar and the cards which are using data from my models.
Any hints on how to achieve this is much appreciated as i'm just a beginner :) Thanks!
You can just pass your form in the get_context_data method [Django-doc]:
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get_context_data(self, *args, *kwargs):
context = super().get_context_data(*args, **kwargs)
context['form'] = SearchBarForm()
return context
or you can make this more declarative, by making use of the FormMixin mxin [Django-doc]:
from django.views.generic.edit import FormMixin
class HomePageView(FormMixin, ListView):
model = Property
template_name = 'home.html'
form_class = SearchBarForm