How to scroll lock a Django HTML Web Page - python

I am currently using a page that has a list of in-line forms
However when the user enters submits each form (line) they are sent back to the top of the page. This becomes really tedious as the users need to enter data quickly and can't when they need to scroll for 2 minutes every time they add an entry.
Does anyone know how to implement a scroll lock to stock this from happening
Views.py: Function:
class AvonleaView( View):
def get(self,request):
created_nums= AvonleaClass.objects.all().values('unitNumber')
Aprev = AvonleaClass.objects.all().order_by('-unitDateEntered')
# created_nums= AvonleaClass.objects.all()
print(created_nums )
created_nums =[int(i['unitNumber']) for i in created_nums]
print(created_nums )
form = AvonleaForm()
return render(request,"meter_readings/avonlea.html",{'form':form , 'created_nums':created_nums })
def post(self,request):
created_nums= AvonleaClass.objects.all().values_list('unitNumber')
print(created_nums)
form = AvonleaForm(request.POST)
if form.is_valid():
form.save()
return redirect('Avonlea')
messages.success(request , 'creates successfully ')
else:
return render(request, 'meter_readings/avonlea.html', {'form': form , created_nums:created_nums })
HTML page :
{% extends 'meter_readings/base.html' %}
{% block content %}
<!-- CSS only -->
<div class="container" font-size= 8px>
<center><h1>Avonlea Meter Readings</h1></center>
<br>
<head>
<meta name="viewport" content="width=device-width">
</head>
{% for unit_number in form.unitNumber %}
<h6>{{ error }}</h6>
<form class="form-group mt-4" method="post" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} >
{% csrf_token %}
<div class="container">
<div class="row mb-3">
<div class="col">
<h5 style="font-size: 14px"> Unit number </h5>
{{ unit_number.data.value}}
</div>
<input type="hidden" name="unitNumber" value="{{unit_number.data.value}}">
<div class="col" id="prev{{unit_number.data.value}}" >
<h5 style="font-size: 14px"> Previous Reading </h5>
{{ previousReading }}
</div>
<div class="col" id="readings{{unit_number.data.value}}">
<h5 style="font-size: 14px"> Current Reading </h5>
{{ form.newReading }}
</div>
<div class="col" id="difference{{unit_number.data.value}}">
<h5 style="font-size: 14px"> Units Used </h5>
{{ form.difference }}
</div>
<div class="col" id="img{{unit_number.data.value}}">
{{ form.image }}
</div>
<div class="col">
<button id="form.id" class="btn btn-success " type="submit" {% if unit_number.data.value in created_nums %} disabled {% endif %} > Save</button>
</div>
</div>
</div>
</form>
{% endfor %}
<br>
<br>

If I understand correctly, you can add #<some_id> to the action attribute of your forms and when the page loads the browser will automatically put the element with the id="some_id" in view.
Example:
<form id="form1" action="#form2" method='POST'>...</form>
...
<form id="form2" action="" method='POST'>...</form>
If you submit #form1 when the page reloads the browser will scroll to #form2 even if it's at the bottom of the page.
Or if you only have one form, you can do:
<form id="form1" action="#form1" method='POST'>...</form>
EDIT:
<form id="form{{forloop.counter0}}" action="#form{{forloop.counter}}" class="form-group mt-4" method="post" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} >

Related

improperly configured at /18/delete, Django views issue

I have searched through the other questions similar to my own problem and have come to no solution so im hoping someone can help me figure out where i went wrong.
I'm trying to implement a delete post option in my blog program but it is throwing the following error once you click the 'delete' button:
ImproperlyConfigured at /18/delete/
Deletepost is missing a QuerySet. Define Deletepost.model, Deletepost.queryset, or override Deletepost.get_queryset().
I am nearly sure its a problem with my URLS.py though what exactly i cannot figure out.
the following is the code in question:
Views.py
# delete post
class Deletepost(LoginRequiredMixin, DeleteView):
form_class = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
urls.py
urlpatterns = [
# home
path('', views.postslist.as_view(), name='home'),
# add post
path('blog_post/', views.PostCreateView.as_view(), name='blog_post'),
# posts/comments
path('<slug:slug>/', views.postdetail.as_view(), name='post_detail'),
# edit post
path('<slug:slug>/edit/', views.Editpost.as_view(), name='edit_post'),
# delete post
path('<int:pk>/delete/', views.Deletepost.as_view(), name='delete_post'),
# likes
path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'),
]
post.html
{% extends 'base.html' %} {% block content %}
{% load crispy_forms_tags %}
<div class="masthead">
<div class="container">
<div class="row g-0">
<div class="col-md-6 masthead-text">
<!-- Post title goes in these h1 tags -->
<h1 class="post-title text-success">{{ post.title }}</h1>
<!-- Post author goes before the | the post's created date goes after -->
<p class="post-subtitle text-success">{{ post.author }} | {{ post.created_on }}</p>
</div>
<div class="d-none d-md-block col-md-6 masthead-image">
<!-- The featured image URL goes in the src attribute -->
{% if "placeholder" in post.featured_image.url %}
<img src="https://codeinstitute.s3.amazonaws.com/fullstack/blog/default.jpg" width="100%">
{% else %}
<img src=" {{ post.featured_image.url }}" width="100%">
{% endif %}
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col card mb-4 mt-3 left top">
<div class="card-body text-dark">
<!-- The post content goes inside the card-text. -->
<!-- Use the | safe filter inside the template tags -->
<p class="card-text text-dark">
{{ post.content | safe }}
</p>
<div class="row">
<div class="col-1">
<strong>
{% if user.is_authenticated %}
<form class="d-inline" action="{% url 'post_like' post.slug %}" method="POST">
{% csrf_token %}
{% if liked %}
<button type="submit" name="blogpost_id" value="{{post.slug}}" class="btn-like"><i class="fas fa-heart"></i></button>
{% else %}
<button type="submit" name="blogpost_id" value="{{post.slug}}" class="btn-like"><i class="far fa-heart"></i></button>
{% endif %}
</form>
{% else %}
<span class="text-secondary"><i class="far fa-heart"></i></span>
{% endif %}
<!-- The number of likes goes before the closing strong tag -->
<span class="text-secondary">{{ post.number_of_likes }} </span>
</strong>
</div>
<div class="col-1">
{% with comments.count as total_comments %}
<strong class="text-dark"><i class="far fa-comments"></i>
<!-- Our total_comments variable goes before the closing strong tag -->
{{ total_comments }}</strong>
{% endwith %}
</div>
<div class="col-1">
<a class="btn btn-outline-danger" href="{% url 'delete_post' post.id %}">Delete It</a>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<hr>
</div>
</div>
<div class="row">
<div class="col-md-8 card mb-4 mt-3 ">
<h3 class="text-dark">Comments:</h3>
<div class="card-body">
<!-- We want a for loop inside the empty control tags to iterate through each comment in comments -->
{% for comment in comments %}
<div class="comments text-dark" style="padding: 10px;">
<p class="font-weight-bold">
<!-- The commenter's name goes here. Check the model if you're not sure what that is -->
{{ comment.name }}
<span class=" text-muted font-weight-normal">
<!-- The comment's created date goes here -->
{{ comment.created_on }}
</span> wrote:
</p>
<!-- The body of the comment goes before the | -->
{{ comment.body | linebreaks }}
</div>
<!-- Our for loop ends here -->
{% endfor %}
</div>
</div>
<div class="col-md-4 card mb-4 mt-3 ">
<div class="card-body">
<!-- For later -->
{% if commented %}
<div class="alert alert-success" role="alert">
Your comment is awaiting approval
</div>
{% else %}
{% if user.is_authenticated %}
<h3 class="text-dark">Leave a comment:</h3>
<p class="text-dark">Posting as: {{ user.username }}</p>
<form class="text-dark" method="post" style="margin-top: 1.3em;">
{{ comment_form | crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-signup btn-lg">Submit</button>
</form>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}
Any ideas?
I think it should be model not form_class so:
class Deletepost(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
#SunderamDubey's answer is correct. The test_func will however not run, since this is method of the UserPassesTestMixin [Django-doc], not LoginRequiredMixin.
But using a test function as is done here is not efficient: it will fetch the same object twice from the database. You can simply restrict the queryset, like:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.views.generic import DeleteView
class DeletePostView(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def get_queryset(self, *args, **kwargs):
return (
super().get_queryset(*args, **kwargs).filter(author=self.request.user)
)
This will do filtering at the database side, and thus return a 404 in case the logged in user is not the author of the Post object you want to delete.
In the template, you will need to make a mini-form to make a POST request, for example:
<form method="post" action="{% url 'delete_post' post.id %}">
{% csrf_token %}
<button class="btn btn-outline-danger" type="submit">Delete</button>
</form>
In my opinion, you should change url to below
'path('delete/int:pk', views.Deletepost.as_view(), name='delete_post'),'
if didn't work you can do this
def delete_post(request, post_id):
post = Post.objects.get(pk=post_id)
post.delete()
return redirect('blog:home')

Django - ListView with form, How to redirect back to the Form page?

So, I have a ListView with exercices list (paginated 1 per page). In each page I have few input the user need to fill up. I managed to find a solution to how to attached the ListView with the Form but i cant find a solution on how to stay on the same page after the submit.
url's:
urlpatterns = [
path('programs/', ProgramListView.as_view(), name='web-programs'),
path('programs/<int:pk>/', ExerciseListView.as_view(), name='program-detail'),
path('data/', views.add_data, name='data-submit'),
views.py (updated with def form_valid):
class ExerciseListView(LoginRequiredMixin,FormMixin, ListView):
model = Exercise
context_object_name = 'exercises'
form_class = DataForm
paginate_by = 1
def get_queryset(self):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
return Exercise.objects.filter(program=program_num)
def form_valid(self, dataform):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
exercises = Exercise.objects.filter(program=program_num)
for exe in exercises:
dataform.instance.exercise = exe.pk
return super(ExerciseListView, self).form_valid(dataform)
def add_data(request):
if request.method == "POST":
form = DataForm(request.POST)
if form.is_valid():
form.save()
# Data.objects.create(address=form.cleaned_data['form'])
return redirect(?)
template.html:
{% extends "program/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h3> Program Exercises List </h3>
{% for exercise in exercises %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
{% if user.is_superuser %}
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'exercise-update' exercise.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'exercise-delete' exercise.id %}">Delete</a>
<p class="article-content">{{ exercise.name }}</p>
{% else %}
<p class="article-content">{{ exercise.name }}</p>
{% endif %}
</div>
<div class="article-metadata">
<p class="article-content">{{ exercise.description }}</p>
<p class="article-content">{{ exercise.breath_method}}</p>
<p class="article-content">{{ exercise.recovery_method }}</p>
<p class="article-content">{{ exercise.measure_method }}</p>
<p class="article-content">{{ exercise.load_share }}</p>
<p class="article-content">{{ exercise.notes }}</p>
<p class="article-content">{{ exercise.extra_info }}</p>
<p class="article-content">{{ exercise.reps }}</p>
<p class="article-content">{{ exercise.sets }}</p>
</div>
<form action="{% url 'data-submit' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Exercise Measurements</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Save</button>
</div>
</form>
</div>
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous Exercise</a>
{% endif %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next Exercise</a>
{% else %}
<a class="btn btn-outline-info mb-4" href="{% url 'web-home' %}">Exit</a>
{% endif %}
{% endif %}
{% endblock content %}
forms.py:
class DataForm(forms.ModelForm):
class Meta:
model = Data
fields = ['exercise', 'set_number', 'spo2', 'hr']
In the views.py, i left the "redirect" with "?" because i don't know what to add there.
I can't change the "action" in the template.html because this link is for def add_data(request)
so it will save my inputs.
Once i submit, it saves the new data to my DB but i don't know how to stay on the same page for continue my exercises.
Thanks.
You have Program in Exercise so use it get program id looking at your DataForm you have exercise field if am not wrong is foreign-key
from django.shortcuts import redirect, reverse
def add_data(request):
page=request.GET.get('page')
page='?page={}'.format(page) if page else ''
if request.method == "POST":
form = DataForm(request.POST)
if form.is_valid():
data=form.save()
return redirect(reverse('program-detail', kwargs={'pk':data.exercise.program.pk})+ page)
For redirecting to same page you check and pass page parmameter in url in form action like
<form action="{% url 'data-submit' %}{%if request.GET.page%}?page={{request.GET.page}}{%endif%}" method="POST" enctype="multipart/form-data">{% csrf_token %}
You need to use jQuery to achieve this result. Download it, paste to js folder and add it to program/base.html
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
I'd like to recommend you to add a js block into base.html
somewhere at the bottom of the file
{% block js %}{% endblock js %}
Then, do this:
<block js>
<script>
$("#submit-btn").submit(function(event) {
// prevent default action, so no page refreshing
event.preventDefault();
var form = $(this);
var posting = $.post( form.attr('action'), form.serialize() );
posting.done(function(data) {
// done
});
posting.fail(function(data) {
// fail
});
});
</script>
<endblock>
...
<form action="{% url 'data-submit' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Exercise Measurements</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" id="submit-btn" type="submit">Save</button>
</div>
</form>

linking search results to a its own detail page

This is a django related question:
I am doing an assignment where we are playing around making a search bar then afterwards letting each individual search result linked to its own page with more details. In this context we are doing a job search engine and I need assistance in when you click each jobs posting, it takes you to a separate page with more info about the job. We already made templates for all the pages. I understand that we have to make a request to the api again after doing it for the view function in the search bar and also use templating got fill up out the detailed search results.Im just not sure how would I apply these concepts to the html file that w ehave.
here's the code
View function code
import requests
from django.shortcuts import render
def home(request):
context = {
'example_context_variable': 'Change me.',
}
return render(request, 'pages/home.html', context)
def search_results(request):
search_query = request.GET['searchterm']
context = {
'result_count': 0,
'search_term': search_query,
}
context['results_count'] = 0
url = 'https://jobs.github.com/positions.json?location=bay+area&description='
url += search_query
response = requests.get(url)
results_data = response.json()
job_list =[]
for result in results_data:
job_list.append(result)
context['job_results'] = job_list
return render(request, 'pages/search_results.html', context)
Search Results Page
{% extends "base.html" %}
{% block title %}
Search Results
{% endblock title %}
{% block additional_styles %}
<style>
body {
background-color: white;
}
</style>
{% endblock %}
{% block content %}
<div id="home-content" class="container">
<div class="row">
<div class="col-lg-3"></div> <!-- Column for spacing -->
<div class="col-lg-6">
<div class="mt-5 mb-3 text-center">
<h1>Search Results</h1>
</div>
<form method="GET" action="/search-results/">
<div class="input-group mb-2">
<input name="searchterm" type="text" class="form-control form-control-lg" placeholder="Let's find a job..." />
<div class="input-group-append">
<button class="btn btn-primary btn-lg">Search</button></a>
</div>
</div>
</form>
<!-- 2start -->
<p>You Searched for: {{search_term}}</p>
{% for job in job_results %}
<div class="list-group">
<a href="/detailed-search-results/" class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{job.title}}</h5>
</div>
<div>
<small class="text-muted">{{job.location}}</small>
</div>
</a>
</div>
<br>
{% endfor %}
<!-- End -->
{% endblock content %}
**detailed Search Results Html file **
So far when you click on a posting it takes you to the detailed search result page without anything on it.
That is because you have hyperlinked each job posting to /detailed-search-results/.
Looking at the API response, you need to change it to job.url
Replace your for loop with this:
{% for job in job_results %}
<div class="list-group">
<a href="{{ job.url }}" class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{job.title}}</h5>
</div>
<div>
<small class="text-muted">{{job.location}}</small>
</div>
</a>
</div>
<br>
{% endfor %}

Django Search bar feature not working?

In my base template I have this search bar. When I search for something it doesn't actually return anything. I'm not sure if the url is correct because I want it to work on every page.
In the base navbar this is the code:
<form class="navbar-form navbar-left" target="_self">
<div class="form-group">
<label class="control-label" for="search-field">
<i class="glyphicon glyphicon-search"></i></label>
<input type="text/submit" value="{{request.GET.q}}" name="q"
class="form-control search-field"
action={% url 'search_posts' %}
placeholder="Search Airline or Aircraft" id="search-field" />
</div>
</form>
Urls.py
url(r'^$', search_posts, name='search_posts'),
Views.py
def search_posts(request):
aircraft = Aircraft.objects.all()
airline = Airline.objects.all()
query = request.GET.get("q")
if query:
aircraft = aircraft.filter(
Q(name__icontains=query) |
Q(description__icontains=query)
).distinct()
return render(request, 'search_post.html', {'aircraft': aircraft})
Is it possible to combine two models into a variable? I have Aircraft and Airline. Will this work?
queryset_list = Aircraft.objects.all() + Airline.objects.all()
Views.py Updated
def search_posts(request):
aircraft = Aircraft.objects.all()
airline = Airline.objects.all()
query = request.GET.get("q")
aircraft = aircraft.filter(
Q(name__icontains=query) |
Q(description__icontains=query)).distinct()
airline = airline.filter(
Q(name__icontains=query) |
Q(description__icontains=query)).distinct()
return render(request, 'search_post.html', {'aircraft': aircraft,'airline': airline })
search_post.html
<div class="team-boxed">
<div class="container">
<div class="row aircraft">
{% for aircraft in aircraft %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ aircraft.image.url }}" />
<h3 class="name">{{ aircraft.name }}</h3>
<h4><em>Range: {{ aircraft.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ aircraft.passengers }}</em></h4>
<h4><em> Speed: {{ aircraft.cruising_speed }} Kt</em></h4>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
Since HTML input elements do not have an action attribute, remove action={% url 'search_posts' %} from <input> and place it inside the <form> like this:
<form action={% url 'search_posts' %} method="GET" ...>
Also remove the type="text/submit" from the input and replace it with just text (in order to present the user a text input box to write the query - thanks Alasdair for that - haven't seen that), like this:
<input type="text" ...>
so, the form should look like this:
<form method="GET" action={% url 'search_posts' %} class="navbar-form navbar-left">
<div class="form-group">
<label class="control-label" for="search-field">
<i class="glyphicon glyphicon-search"></i></label>
<input type="text" value="{{request.GET.q}}" name="q" class="form-control search-field" placeholder="Search Airline or Aircraft" id="search-field" />
</div>
</form>
Concerning the other part of your question, in order to combine two (or more) QuerySets (I can't imagine why you would want to do that), here it is:
qs = list(Aircraft.objects.all()) + list(Airline.objects.all())
Finally in your search_post.html do this:
{% if aircraft.exists %}
<div class="team-boxed">
<div class="container">
<div class="row aircraft">
{% for aircraft in aircraft %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ aircraft.image.url }}"></div>
<h3 class="name">{{ aircraft.name }}</h3>
<h4><em>Range: {{ aircraft.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ aircraft.passengers }}</em></h4>
<h4><em> Speed: {{ aircraft.cruising_speed }} Kt</em></h4>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% if airline.exists %}
<div class="team-boxed">
<div class="container">
<div class="row airline">
{% for airline in airline %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ airline.image.url }}"></div>
<h3 class="name">{{ airline.name }}</h3>
<h4><em>Range: {{ airline.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ airline.passengers }}</em></h4>
<h4><em> Speed: {{ airline.cruising_speed }} Kt</em></h4>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}

django-bootstrap-toolkit for my contact page

I'm new to django. I'm using django-bootstrap-toolkit for my contact page. It works fine when I test it locally. But I'm getting an error on my hosting server, while all other pages work just fine.
Exception Type: TemplateDoesNotExist
Exception Value: bootstrap_toolkit/form.html
Here is contact_us.html page
bootstrap_toolkit/form.html
{% extends 'base.html' %}
{% load bootstrap_toolkit %}
{% block content %}
<div id="wrap">
<div class="container">
<div class="page-header">
<h1 id="contact">Contact</h1>
</div>
<div class="form well" >
<h4 class="">Feedback</h4>
<p class="">Thank you for downloading BookxGeek. I look forward to hearing your feedback!</p>
<form action="." method="post" class="form" >
{% csrf_token %}
{% bootstrap_form form layout="vertical" %}
<br>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
<hr class="soft">
</div>
{% endblock %}

Categories