Update table every time my database is changed [HTMX][Dajngo-tables2] - django

I want to Update table every time my database is changed, without refreshing. Also, I want to keep my quarry parameters from a search when the update happens
What I done so far is use hx-get to retrieve my table from another template and view to get me the updated table.
However, I don't know where to start to trigger a update when the database is changed
Views.py
def display_view(request):
myFilter = ParticipantFilter(request.GET, queryset=Participant.objects.all())
table = ParticipantTable(myFilter.qs)
table.paginate(page=request.GET.get("page", 1), per_page=10)
return render(request, 'display.html', {'table': table,'myFilter': myFilter})
def data_only_view(request):
myFilter = ParticipantFilter(request.GET, queryset=Participant.objects.all())
table = ParticipantTable(myFilter.qs)
table.paginate(page=request.GET.get("page", 1), per_page=10)
return render(request, 'updatedDisplay.html', {'table': table})
display.html
{% extends "base.html" %}
{% block content %}
<form method="get">
{{ myFilter.form }}
<button type="submit">Search</button>
</form>
<div id="table-results" hx-get="/updatedDisplay" hx-include = "[name='first_name']">
{% load render_table from django_tables2 %}
<table class="table">
{% render_table table %}
</table>
{% endblock %}
</div>
updateDisplay.html
{% load render_table from django_tables2 %}
<table class="table">
{% render_table table %}
</table>

Related

update table using SQL INSERT not working in Flask App

So I have searched through existing questions based on my challenge and I haven't found any solution. I need help with updating a database by inserting a new value into a column that was hitherto null during the creation of the table. The code below is a route for profile. The first thing it does is to check if it the user that signed in. If not the user, the user is redirected to a login page. However, if it is the user I want the user to select a value from a drop-down list and then add the value to the users' table where the country column is set initially to NULL. Currently, it is not adding the record to the database. On selection of the value, the value is not updated in the database. The country column I am trying to update remains null/empty
APP.PY
#app.route('/profile', methods=['GET', 'POST'])
def profile():
form = CountryForm(request.form) # A drop down list from where user select a value
first = request.form.get('country_select')
if not g.user:
return redirect(url_for('login'))
else:
if request.method == 'POST' and form.validate():
try:
with sqlite3.connect("tour.db") as con:
cur = con.cursor()
print("Opened database successfully")
cur.execute("INSERT INTO users (country) VALUE (?)",(first) )
con.commit()
flash("Record successfully added")
except:
con.rollback()
flash("error in insert operation")
finally:
return render_template("profile.html", msg = first)
con.close()
return render_template('profile.html', user=get_curr_user(), form=form, country=first)
profile.html
{% extends "base.html" %}
{% block head %}
<title>Profile Page</title>
{% endblock %}
{% block body %}
<h1 class="title">
Welcome, {{g.user.username}}
</h1>
<form method="POST" action="{{ url_for('profile') }}">
<select name="country_select">
{% for x in form.country %}
<option>{{ x }}</option>
{% endfor %}
</select>
<input type="submit" value="submit">
</form>
<p>{{country}}</p>
<div class="auth-wrapper">
Log out
</div>
{% endblock %}
base.html
<html>
<body onload="brython(1)">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
{% endwith %}
{% block body %} {% endblock %}
<script type=”text/python” src=”script/program.py”></script>
</body>
</html>
Looking forward to your contributions. Thanks.

How do I use django_tables2 with a filter?

I'm displaying data on a webpage, and I would like to migrate this code to use the table I created in tables.py. I can't figure out how to do it without breaking the filter.
views.py
def PlatListView(request):
queryset = Plat.objects.all().values('id', 'description','status', 'phase__number','phase','schedule_found').annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})
filters.py
class PlatFilter(django_filters.FilterSet):
community = ModelChoiceFilter(queryset=Community.objects.all())
tables.py
import django_tables2 as tables
class PlatTable(tables.Table):
id = tables.Column()
description = tables.Column()
status = tables.Column()
phase__number = tables.Column()
lot_count = tables.Column()
schedule_found = tables.Column()
class Meta:
ordering = 'description'
#model = Plat
filtertable2.html
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
<table>
<tr>
<th>Description</th>
<th>Status</th>
</tr>
{% for obj in filter.qs %}
<tr>
<td> {{ obj.description }}</td>
<td>{{ obj.status }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
In your view you construct the table with the data from the filter:
def PlatListView(request):
queryset = Plat.objects.annotate(
lot_count=Sum('phase__lot_count')
).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
table = PlatTable(data=f.qs)
return render(request, 'blog/filtertable2.html', {'filter': f, 'table': table})
You can then render the table with:
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
{% load render_table from django_tables2 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% render_table table %}
{% endblock content %}
I do not see any particular reason for using Values QuerySet, ie values(). You can simply annotate the value with queryset:
def plat_list_view(request): # using snake_case when defining a method name.
queryset = Plat.objects.annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})

djang-bootstrap avoid label tag being added when calling `field|bootstrap`

How to avoid label tag being added when calling field|bootstrap. I have the below code
filter.py
import django_filters
from .models import Issue
class IssuesFilter(django_filters.FilterSet):
summary = django_filters.CharFilter(label="Summary", lookup_expr="icontains")
class Meta:
model = Issue
Views.py
def index(request):
issues = IssuesFilter(request.GET, queryset=Issue.objects.all())
context = {
'user': request.user,
'message': 'LogedIn',
'filter': issues
}
return render(request, 'testApp/index.html', context)
index.html
{% extends "firstPage/base.html" %}
{% load bootstrap %}
{% load render_table from django_tables2 %}
{% load crispy_forms_tags %}
{% block body %}
<form method="GET">
<table>
{% for field in filter.form %}
<tr class="table table-borderless">
<td>{{ field.label_tag }}</td>
<td>{{ field|bootstrap }}</td>
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-primary">Search</button>
</form>
{% endblock %}
When I add field|bootstrap I could see the label tag of the field is displayed. Is it possible to remove additional label tag from being added?
I know this comes very late but if anyone is dealing with the same problem you can find the answer in the documentation
https://django-bootstrap4.readthedocs.io/en/latest/templatetags.html#bootstrap4.templatetags.bootstrap4.bootstrap_field
{% bootstrap_field field show_label=False %}

How to combine ListView and UpdateView

In my web application, I have a template with ListView that shows list of table records, that works fine.
Now I want to allow user to update fields for each row of the table.
One "easy" solution is to create an update page using UpdateView and put a link to it in each row. User can then click update, open update page ... But I am wondering if there is a way to update fields in the same table, without opening a new page.
Hope my question is clear.
thanks for your help
UPDATE (and "my" solution)
I managed to do it using formset:
in forms.py
class IssueForm(forms.ModelForm):
class Meta:
model=Issue
fields=('__all__')
IssueFormset=inlineformset_factory(IssuesList, Issue, form=IssueForm,extra=0)
in views.py
class IssuesListUpdateView(UpdateView):
model=IssuesList
fields='__all__'
# ovewrite get_context_data to add formset as an additionnal parameter
def get_context_data(self, **kwargs):
context = super(IssuesListUpdateView, self).get_context_data(**kwargs)
if self.request.POST:
# if Save All issues button submitted
if 'save_all' in self.request.POST.keys():
formset = IssueFormset(self.request.POST, instance=self.object)
# sending formset to the template
context['issues_formset'] = formset
# save in the DB (saves only what has changed)
#https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/#saving-objects-in-the-formset
# if formset.is_valid():
formset.save()
# re-update context with new formset, this is need to refresh table in case of deleting an object
# without this, issue is deleted but still visible in the table
context['issues_formset'] = IssueFormset(instance=self.object)
else:
# sending formset to the template
context['issues_formset'] = IssueFormset(instance=self.object)
return context
In template:
<form method="post">{% csrf_token %}
<!-- Below line is important to avoid django exception:
[django 'ManagementForm data is missing or has been tampered with] -->
{{ issues_formset.management_form }}
<input name="save_all" type="submit" value="Save All Issues">
<div class="">
<table id="formset" class="form" border="1">
{% for form in issues_formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr></thead>
{% endif %}
<tr>
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
</form>
hope it will help someone, please let me know if you have any comments

How to fix pagination after making a search for specific data in django_tables2

In my project I am using with success django_tables2 in order to achieve server side processing.
The only thing that I do not know how to handle is that after searching, for example by name in a template rendering clients for my application, the search despite the fact that gives some returned results based on the name, it is not working properly if the result records are spread in more than one page based on my pagination.
In other words, when I am clicking the 2 (second page of my returned results), the app is showing all the pages concerning the clients 1 2 3 ...45 next (as i want to reach the /clients/ url, and not the 1 2 next structure for only the custom search data.
This happening also when I am clicking the next and previous buttons.
One easy solution It could be to increase my pagination limit in order to show all the possible results in one page, but this solution is not proper for big result sets.
Is there any solution to avoid loading and showing all the pages in the search bar and only keeping the results of my custom search?
Below is my snippets.
url.py
url(r'^clients/$', views.client_list, name='client_list'),
models.py
class Client(models.Model):
name = models.CharField(max_length=50, verbose_name="Name")
surname = models.CharField(max_length=50, verbose_name="Surname")
activity = models.IntegerField(choices=ACTIVITY_OPTIONS, null=True,default=ACTIVE)
views.py
def client_list(request, template_name='clients/client_list.html'):
if request.method == 'POST':
search_string = request.POST['search_client']
current_client=Client.objects.filter(Q(activity=1) & Q(name=search_string)| Q(surname=search_string))
single_table=ClientTable(current_client)
RequestConfig(request).configure(single_table)
return render(request,template_name, {'single_table': single_table})
else:
clients=Client.objects.filter(activity=1)
table = ClientTable(clients)
RequestConfig(request).configure(table)
return render(request,template_name, {'table': table})
tables.py
class ClientTable(tables.Table):
class Meta:
#define the model
model = Client
exclude=('..')
template_name = 'django_tables2/bootstrap.html'
sequence = ("surname", "name",)
template
{% extends 'base.html' %}
{% load has_group %}
{% load render_table from django_tables2 %}
{% load bootstrap3 %}
{% load static %}
{% load staticfiles %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12">
<form class="well" method="post" action="">
{% csrf_token %}
Client Search:<br>
<input type="text" class="form-control" id="search" name="search_client">
<br>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "like" %} Submit
</button>
{% endbuttons %}
</form>
{% if single_table %}
{% render_table single_table %}
{% endif %}
{% if table %}
{% render_table table %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
Finally after searching I found a solution.
Django filters https://django-filter.readthedocs.io/en/master/index.html can be used in situations like this one.
The steps I followed are:
1) import the 'django_filters', to settings.py
2) Define the filters.py
import django_filters
from .models import Patient
class ClientFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Client
fields = ['id','name','surname']
3) Modify the views.py
class FilteredClientListView(SingleTableMixin, FilterView):
table_class = ClientTable
model = Client
template_name ='clients/client_list2.html'
filterset_class = ClientFilter
4) Modify urls.py accordingly since I used class based function
url(r'^clients2/$', views.FilteredClientListView.as_view(), name='client_list2'),
5) Modify my template
{% extends 'base.html' %}
{% load has_group %}
{% load render_table from django_tables2 %}
{% load bootstrap3 %}
{% load static %}
{% load staticfiles %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12">
<form class="well" method="post" action="">
{% csrf_token %}
Client Search:<br>
<input type="text" class="form-control" id="search" name="search_client">
<br>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "like" %} Submit
</button>
{% endbuttons %}
</form>
{% if filter %}
<form action="" method="get" class="form form-inline">
{% bootstrap_form filter.form layout='inline' %}
{% bootstrap_button 'filter' %}
</form>
{% endif %}
{% if single_table %}
{% render_table single_table %}
{% endif %}
{% if table %}
{% render_table table %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
P.S : importing in the views.py the appropriate tables and filters