How do I add Pagination to a table (Django) - python-3.x

I am trying to add pagination to one of the tables for my project, but I can't find any good resources to refer to, all of the docs use some kind of URL query, but I don't want to do that, since it is on the user page.
Background --- I am making a mock website for trading for a project and I need the user to be able to see their trade history, and as you can imagine, after any more than 10, the page starts to look very long, so I am trying to find a way to make the table have pages, but I just can't figure it out.
Aim -- To add pages to a bootstrap table. The table should be able to go back and forth using buttons.
My "solution" - after going through stuff for about an hour, I found this but I don't know if it is good/safe.
Code :
VIEW -
def userPage(request):
user = request.user
user_info = user.info
trades = user_info.trade_set.all().order_by('-time_bought_at') ###I want this queryset to be paginated
total_trades = trades.count()
balance = round(user_info.balance)
context = {
"user" : user,
"user_info" : user_info,
"trades" : trades,
"total_trades" : total_trades,
"balance" : balance,
}
return render(request, "accounts/user.html", context)
I render it as :
this is the table that I want to paginate :)
<div class="row">
<div class="card card-body">
<table class="table table-sm">
<tr>
<th>Stock</th>
<th>Action</th>
<th>Price</th>
<th>No. of Stocks</th>
<th>Total Cost of Trade</th>
<th>Time of Purchase</th>
<th>Balance</th>
</tr>
{% for trade in trades %}
<tr>
<td>{{trade.ticker}}</td>
<td>{{trade.action}}</td>
<td>{{trade.price_trade_at}}</td>
<td>{{trade.stocks_bought}}</td>
<td>{{trade.cost_of_trade}}</td>
<td>{{trade.time_bought_at}}</td>
<td>{{trade.balance_of_trader_after_purchase}}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
Please point me in the correct direction, I got no clue.

Try using ajax to serve your table
def userPage(request):
user = request.user
user_info = user.info
trades = user_info.trade_set.all()
total_trades = trades.count()
balance = round(user_info.balance)
context = {
"user" : user,
"user_info" : user_info,
"total_trades" : total_trades,
"balance" : balance,
}
return render(request, "accounts/user.html", context)
class TradesListView(ListView):
template_name = 'mytemplate.html'
ordering = '-time_bought_at'
paginate_by = 10
def get_queryset(self):
user_info = self.request.user.info
self.queryset = user_info.trade_set.all()
return super().get_queryset()
In the templates:-
In the template for the trades list view:-
<div class="card card-body">
<table class="table table-sm">
<tr>
<th>Stock</th>
<th>Action</th>
<th>Price</th>
<th>No. of Stocks</th>
<th>Total Cost of Trade</th>
<th>Time of Purchase</th>
<th>Balance</th>
</tr>
{% for trade in page_obj %}
<tr>
<td>{{trade.ticker}}</td>
<td>{{trade.action}}</td>
<td>{{trade.price_trade_at}}</td>
<td>{{trade.stocks_bought}}</td>
<td>{{trade.cost_of_trade}}</td>
<td>{{trade.time_bought_at}}</td>
<td>{{trade.balance_of_trader_after_purchase}}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<button class="page-change-btn" data-url="{% url 'trades-list-view-name' %}?page=1">« first</button>
<button class="page-change-btn" data-url="{% url 'trades-list-view-name' %}?page={{ page_obj.previous_page_number }}">previous</button>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<button class="page-change-btn" data-url="{% url 'trades-list-view-name' %}?page={{ page_obj.next_page_number }}">next</button>
<button class="page-change-btn" data-url="{% url 'trades-list-view-name' %}?page={{ page_obj.paginator.num_pages }}">last »</button>
{% endif %}
</span>
</div>
In the template for the userPage:-
<div class="row" id="trades-table-container" data-url="{% url 'trades-list-view-name' %}">
</div>
Now use some javascript to perform ajax and use the url in the data-url of above div and fill the content of response into the div.
Also add javascript on the page-change-btn class in similar fashion

Related

How to get the table details based on post request django

**views.py**
[if request.method == "POST":
from_date = request.POST.get("from_date")
print(from_date)
to_date = request.POST.get("to_date")
print(to_date)
get_date_from_dates = Scrapper.objects.all().filter(created_at=from_date, updated_at=to_date)
print(len(get_date_from_dates))
page = request.GET.get('page', 1)
paginator = Paginator(get_date_from_dates, 5)
global users
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
else:
user_list = Scrapper.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(user_list, 5)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
return render(request, "home.html", { 'users': users })
return render(request, "home.html", {'users': users})][1]
**home.html**
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<body>
<style>
h2 {text-align: center;}
</style>
<h1>Facilgo Completed Jobs</h1>
<form action="" method="post">
{% csrf_token %}
<label for="from_date">From Date:</label>
<input type="date" id="from_date" name="from_date">
<label for="to_date">To Date:</label>
<input type="date" id="to_date" name="to_date">
<input type="submit"><br>
</form>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Summary Details</h2>
<table id="bootstrapdatatable" class="table table-striped table-bordered" width="100%">
<thead>
<tr>
<th>user_registration_source_id</th>
<th>user_type</th>
<th>user_id</th>
<th>source</th>
<th>source_url</th>
<th>created at</th>
<th>updated at</th>
</tr>
</thead>
<tbody>
{% for stud in users %}
{% csrf_token %}
<tr>
<td>{{stud.user_registration_source_id}}</td>
<td>{{stud.user_type}}</td>
<td>{{stud.user_id}}</td>
<td>{{stud.source}}</td>
<td>{{stud.source_url}}</td>
<td>{{stud.created_at}}</td>
<td>{{stud.updated_at}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if users.has_other_pages %}
<ul class="pagination">
{% if users.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% if user.number|add:'-4' > 1 %}
<li>…</li>
{% endif %}
{% for i in users.paginator.page_range %}
{% if users.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% elif i > users.number|add:'-5' and i < users.number|add:'5' %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if users.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
</div>
</div>
</body>
</html>
Webpage
When I post my from date and to date it would check the "created at" and "updated at" field in table and able to view only the datas of particular date. I have written the post request and get the from date and to date from the form. Is there any solution after posting data only get the values of particular dates in table. But at the opening the webpage it should show all datas in table
Output:
Output Image
I think its better approach to use a certain time period if not chosen by the user. for example one month range.
from datetime import date as dt
from dateutil.relativedelta import relativedelta
if request.method == "POST":
if "from_date" and "to_date" in request.POST:
from_date = request.POST.get("from_date")
to_date = request.POST.get("to_date")
else:
from_date = dt.today()
to_date = today + relativedelta(months=+1)
and then filter with this dates.

Show image name inside the image field in Django forms

I have this edit or update form in which I want to display only the image name in the form for a better user experience so that the user could know which image he has uploaded while creating the data.
I am storing the image name in the model as well,but i want to display the image name inside the image field.
forms.py
class MenuCategoryForm(forms.ModelForm):
image = forms.ImageField(allow_empty_file=True, required=False)
class Meta:
model = MenuCategory
fields = ['name', 'description', 'menu_options']
view
def menu_category_update(request, id):
item = MenuCategory.objects.get(id=id)
if request.method == 'POST':
form = MenuCategoryForm(request.POST, request.FILES, instance=item)
if form.is_valid():
if request.FILES['image']:
image = request.FILES['image']
image_url = upload_image(image, 'menu_category', image.name)
obj = form.save(commit=False)
obj.image_url = image_url
form.save()
else:
form.save()
return redirect('menu-category')
else:
form = MenuCategoryForm(instance=item)
context = {
'form': form,
'item': item
}
return render(request, 'menu/menu_category_update.html', context)
Template
{% extends 'partials/base.html' %} {% load crispy_forms_filters %} {% load
crispy_forms_tags %}
<!-- {% block title %}Menu category {% endblock %} -->
{% block content %}
<div class="container edit-form-flex">
<div class="row Edit-form-box">
<div class="form-inner-box bg-white">
<div class="heading-editing">
<h3>Edit menu category</h3>
</div>
<form method="POST" class="add-new-form edit-form" enctype="multipart/form-data">
{% csrf_token %} {{ form|crispy }}
<div class="update-buttons-container">
<button class="btn btn-info1" type="submit" value="Update">
Update
</button>
<a class="btn btn-secondary" href="{% url 'menu-category' %}"
>Cancel</a
>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
Well in other to get the name of the image in your form you will be better off in using a form initial like so:
def menu_category_update(request,id):
item = MenuCategory.objects.get(id=id)
if request.method == 'POST':
form = MenuCategoryForm(request.POST, request.FILES, instance=item)
if form.is_valid:
obj = form.save(commit=False)
# obj.username = request.user
form.save()
return redirect('menu-category')
else:
form = MenuCategoryForm(
initial={'image':item.image,
'name':item.name,
'description':iteem.description,
})# this are the fields that we want to show in the form
context = {
'form': form,
'item': item
}
return render(request, 'menu/menu_category_update.html', context)
In your form html you will apply the form initial to the field that you want to show in your form, by doing something like this: form.initial.name As i have illustrated below :
{% extends 'partials/base.html' %} {% load crispy_forms_filters %} {% load
crispy_forms_tags %}
<!-- {% block title %}Menu category {% endblock %} -->
{% block content %}
<div class="container edit-form-flex">
<div class="row Edit-form-box">
<div class="form-inner-box bg-white">
<div class="heading-editing">
<h3>Edit menu category</h3>
</div>
<form method="POST" class="add-new-form edit-form" enctype="multipart/form-data">
{% csrf_token %}
<label> Image name </label>
{{form.initial.name}}
<label> Description </label>
{{ form.initial.description }}
<label> Image </label>
{{ form.initial.image }}
<div class="update-buttons-container">
<button class="btn btn-info1" type="submit" value="Update">
Update
</button>
<a class="btn btn-secondary" href="{% url 'menu-category' %}"
>Cancel</a
>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

Cannot query "Python Tutorials Teaser": Must be "Subject" instance

I am creating E-Learning website and I want to show "Course Content or Lession" as a playlist which is related to subject. Like that image
but I am getting error Cannot query "Python Tutorials Teaser": Must be "Subject" instance. Python Tutorials Teaser is title of the lession.
view.py
def allsubject(request):
subj = Subject.objects.all()
context = {'subj': subj}
return render(request, 'allsubject.html', context)
def pvideos(request, slug):
vds = Videos.objects.filter(slug=slug).first()
coursecontent = Videos.objects.filter(subject=vds)
context = {'vds':vds, 'coursecontent':coursecontent}
return render(request, 'pvideos.html', context)
models.py
class Videos(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=500)
cont = models.TextField()
vurl = models.URLField(max_length=200)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, related_name='videos')
position = models.PositiveSmallIntegerField(verbose_name="videono.")
slug = models.CharField(max_length=130)
timeStamp = models.DateTimeField(default=now)
def __str__(self):
return self.title
pvideo.html
{% extends 'base.html' %}
{% block title %}Free Video Course {% endblock title %}
{% block body %}
<div class="container">
<div class="embed-responsive embed-responsive-21by9">
<iframe class="embed-responsive-item" src="{{vds.vurl}}" allowfullscreen></iframe>
</div>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active font-weight-bold" id="home-tab" data-toggle="tab" href="#overview" role="tab"
aria-controls="home" aria-selected="true">Overview</a>
</li>
<li class="nav-item">
<a class="nav-link font-weight-bold" id="profile-tab" data-toggle="tab" href="#coursecontent" role="tab"
aria-controls="profile" aria-selected="false">Course Content</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="home-tab">
<h2>{{vds.title}}</h2>
<p>{{vds.cont|safe}}</p>
</div>
<div class="tab-pane fade" id="coursecontent" role="tabpanel" aria-labelledby="profile-tab">
{% for c in coursecontent %}
{{c.title}}
{% endfor %}
</div>
</div>
</div>
{% endblock body %}
I think I made a mistake on views.py coursecontent = Videos.objects.filter(subject=vds). I want to show this playlist on that page where I show lessions. I hope you understand what I want. If anyone has any other idea besides this, so please help me.
I user click on course content then I show all lession related to subject
You are right, you have made a mistake in coursecontent = Videos.objects.filter(subject=vds)
Subject must either be the pk or an instance of subject but you're giving it another video instance. What you want is
coursecontent = Videos.objects.filter(subject=vds.subject).exclude(sno=vds.sno)
.filter(subject=vds.subject) will give you all videos with the same subject.
.exclude(sno=vds.sno) will exclude the current video from the query. This is useful if you want to show only the other videos... If you want to include all, just skip that part.
As a side note, you might want to improve your variable naming.
vds could be called video (it's singular)
vurl could be just url
cont could be content
Most of your model names should be singular (coz each is a single instance).
An e-learning website is a nice initiative.

How to select an instance of a model from a queryset django?

I am creating a project for hosting cricket tournaments. I have created 3 apps in it: home, tournament and team. After adding a tournament, when entering the tournament's detail view, I can add a team to the tournament. My Team model has a ForeignKey to my Tournament model, and my Tournament model has a ForeignKey to my User model(built-in django user model). When creating a team, I want to save the team for a particular tournament. I don't understand how to access the exact tournament and save the team for that tournament only.
My tournament detail html:
{% extends 'menu.html' %}
{% block content %}
<div class="row">
<div class="col-8">
<table class="table table-bordered table-hover">
<tr>
<th scope="col">Match between</th>
<th scope="col">Winner</th>
</tr>
{% for match in match_list %}
<tr>
<td>
{{ match.team1.name }} vs {{ match.team2.name }}
</td>
<td>
{% if match.winner %}
{{ match.winner.name }}
{% else %}
TBD
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<div class="col-4">
{% if teamscount < tournament.no_of_teams %}
<button class="btn btn-primary" onclick="window.location.href='{% url 'teams:addteam' %}'">Add Team</button>
{% endif %}
</div>
</div>
{% endblock content %}
My urls.py file in tournament app:
from django.urls import path, include
from . import views
app_name='tournaments'
urlpatterns = [
path('all/', views.TournamentListView.as_view(), name='all'),
path('create/', views.TournamentCreateView.as_view(), name='create'),
path('view/<int:pk>/', views.TournamentDetailView.as_view(), name='detail'),
]
My urls.py file in teams app:
from django.urls import path
from . import views
app_name="teams"
urlpatterns = [
path('new/', views.TeamCreateView.as_view(), name="addteam"),
]
My views.py file in teams app:
from django.shortcuts import render
from django.views.generic import CreateView
from .models import Team
from django.urls import reverse_lazy
from tournament.models import Tournament
class TeamCreateView(CreateView):
model = Team
fields = ['name', 'no_of_players',]
success_url = reverse_lazy('tournaments:all')
success_message = "Tournament Created!!"
def get_form(self):
form = super().get_form()
return form
def form_valid(self, form):
print('form_valid called')
object = form.save(commit=False)
object.tournament = Tournament.objects.filter(user = self.request.user)
object.save()
return super(TeamCreateView, self).form_valid(form)
My create team html file:
{% extends 'menu.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{{ form.media }}
<form
action="{% url 'teams:addteam' %}"
method="post"
id="upload_form"
enctype="multipart/form-data"
>
{% csrf_token %} {{ form|crispy }}
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Create</button>
<input class="btn btn-danger" type="submit" onclick="window.location='{% url 'tournaments:all' %}' ; return false;" value="Cancel" />
</div>
</form>
{% endblock content %}
How can I save this team to the specific tournament model, or do I need to change the way I've designed the functions and classes?
For what i understood your models have the following design:
class Tournament(models.Model):
name = models.CharField(max_length=50)
user = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE
)
def __str__(self):
return self.name
class Team(models.Model):
name = models.CharField(max_length=50)
tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
def __str__(self):
return self.name
So, if you want to save a Team instance to a specific Tournament, you need to do the following:
# Grab the tournament instance in a variable (I recommend to use the id instead of the user. This is probably better, unless the user is unique per tournament, if not .get() will throw an error )
tournament = Tournament.objects.get(user=user)
# Then create your Team object like this
Team.objects.create(name='super team', tournament=tournament)
One of the problems i see is that you are using 'filter' alone to try to get an instance. 'Filter' returns a QuerySet. You have many choices to return a specific instance after using 'filter', you can do .filter().first() or .filter()[0] (or any number) and there are more

Edit and Update Method is Not working

My problem is, edit and update the values by using python-flask from client side. I don't have any idea about that and new python-flask using MySQL database. I tried this method for edit and update purpose.But, it's not working.Additionally the details will be added in database when we enter details and submit. anyone help me.
Here is vehicletype.html template.
{% extends "base.html" %}
{% block head %}
{{super()}}
{% endblock %}
{% block navbar %}
{{super()}}
{% endblock %}
{% block content %}
<div class="row">
<ol class="breadcrumb">
<li><a href="#">
<em class="fa fa-home"></em>
</a></li>
<li class="active">Vehicletype > Create Vehicletype</li>
</ol>
</div>
<div class="row">
<div class="col-md-6">
<form role="form" action="/post/vehicletype" method="post">
<div class="form-group">
<label>VehicleType: </label>
<input name="type" class="form-control" placeholder="enter vehicletype">
</div>
<input type="submit" class="btn btn-primary" value="Submit ">
<input type="reset" class="btn btn-default" value="Reset">
</form>
</div>
</div>
{% endblock %}
Here is the details.html
{% extends "base.html" %}
{% block head %}
{{super()}}
{% endblock %}
{% block navbar %}
{{super()}}
{% endblock %}
{% block content %}
<div class="row">
<ol class="breadcrumb">
<li><a href="#">
<em class="fa fa-home"></em>
</a></li>
<li class="active">Vehicletype>View</li>
</ol>
</div><!--/.row-->
<div class="row">
<div class="col-md-12">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
Id
</th>
<th>
VehicleType
</th>
<th>
Dateofsub
</th>
<!--<th>
Control
</th>-->
<th>
Delete
</th>
</tr>
</thead>
{% for values in vehicletype %}
<tr>
<th>{{values.id}}</th>
<td>{{values.type}}</td>
<td>{{values.dateofsub}}</td>
<!--<td>Reset Password</td>-->
<td>Delete</td>
<td>edit</td>
</tr>
{% endfor %}
</table>
<em class="fa fa-xl fa-plus-circle color-blue" ></em>
</div>
</div>
{% endblock %}
python code for Edit method:
class VehicetypeForm(FlaskForm):
type=StringField('Type')
#app.route('/control/edit/<int:id>',methods=['POST','GET','PATCH'])
def edit(id):
form = VehicetypeForm(request.form)
mysql = pymysql.connect("0.0.0.0", "tnxt", "tnxt", "transport")
cur = mysql .cursor()
cur.execute('SELECT * FROM vehicletype WHERE id= %s',[id])
type=cur.fetchall()
# form.type.data=type
if request.method=='PATCH' and form.validate():
#type=form.type.data
mysql = pymysql.connect("0.0.0.0", "tnxt", "tnxt", "transport")
cur=pymysql .cursor()
cur.execute('UPDATE vehicletype SET type=%s WHERE id=%s',(type,id))
mysql.connection.commit()
cur.close()
flash('success')
return redirect(url_for('vehicle_type'))
return render_template('vehicletype.html',form=form)
In this python code update method is not working. But, when we give the details that details will be added in database. How to edit and update the values from client side.
Below is the good practice to create form using wtforms
class UserForm(Form):
name = StringField('Name')
father_name = StringField('Father Name')
# .... add fields you want
for field types - refer to this link
#app.route('/newuser', methods=['GET', 'POST'])
def add_user():
form = UserForm()
if form.validate_on_submit():
user_details = {
name: form.name.data,
fathername: form.father_name.data,
# add more fields
}
sqlsession.add(user_details)
return redirect(url_for('page_newuser'))
return render_template('newuser.html', form=form)
Once you have form then you can easily edit your content and directly save it to database
#app.route('/control/edituser/<int:id>',method=['post','get'])
def edit(id):
qry=sqlsession.query(Enduser).filter(Enduser.id==id).first()
form = UserForm(request.form, **qry)
if form.validate_on_submit():
form.populate_obj(qry)
sqlsession.update(qry)
sqlsession.commit()
return redirect(url_for('page_newuser'))
return render_template('newuser.html', form=form)

Resources