Hey i am new to Django and I am trying to make a search bar to my first site.
My problem here is when I search for any value that I/user entered and on the site, the site only refreshes and doesn't give me anything back but the empty option that i gave the site to display when there is no content to match the search.
(That's not all of the Topic model)
model.py
class Topic(models.Model):
content = models.CharField(max_length=200)
views.py
def search(request):
query = request.GET.get('q')
if query:
result = Topic.objects.filter(content__icontains=query)
context = { 'query': query, 'result': result}
return render(request, 'learning_logs/topics.html', context)
(that's all of the topics.html i am sorry of how it turned this not what it really looks like on the original topics.html but that's the full topics.html )
topics.html
% extends "leaning_logs\base.html" %}
{% block page_header %}
<h1>Topics </h1>
<br>Add a new topic</br>
{% endblock page_header %}
{% block content %}
<form method="GET" action="{% url 'learning_logs:search' %}">
{% csrf_token %}
<input name="q" value="{{ request.GET.q }}" placeholder="search..">
<button class="btn btn-success" type="submit">
Search</button>
</form>
{% for topic in topics %}
<div class="card-mb3">
<div class="card-header" style="background-color:lightgrey">
<table class="table">
<tr>
<th>Image</th>
<th>Title of the topic</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<div class="card-body" style="background- color:white">
<tr>
<td>
{% if topic.image %}
<image src="{{topic.image.url}}" style="width:200px">
{% else %}
<span class="text-muted">No Image have been added</span>
{% endif %}
<td><h3>
{{topic}}
</td></h3>
<td><small><a href="{% url 'learning_logs:edit_topic' topic.id %}">
<button method="submit" class="btn btn-primary">
Edit topic</button></a></small></td>
<td><small><form method="post" action="{% url 'learning_logs:delete_topic' topic.id %}">
<button type="submit" class="btn btn-danger btn-primary" >
Delete topic</button></form></small></td>
</tr>
</div>
</div>
</div>
{% empty %}
<h3><li>No topics have been added yet.</li></h3>
{% endfor %}
{% endblock content %}
This:
{% for topic in topics %}
should be that:
{% for topic in result %}
Related
I am trying to implement filter buttons in my django formset and found a solution that would allow user to do that asynchronously.
I tried to use code from here but my html is more complex and I don't know how to filter each row based on text in Product column.
My problem is that I am not sure how to pass related_product name as value or as text in jQuery function so when I select test product it will show me only rows that contain "test product" text:
So what should I put as class name in $('tbody tr').show(); to get related_product title and show all rows that contains this related_product title?
views.py
class ProductComponentView(TemplateView):
template_name = "formset.html"
def get(self, *args, **kwargs):
get_components = CostCalculator.objects.all()
get_datetime = timezone.now().strftime('%Y-%m-%dT%H:%M:%S')
product_list = Product.objects.filter(status=1)
formset = RequestFormset(initial=[{
'author': self.request.user.email,
'related_product': component.related_product,
'related_component': component.id,
'created': get_datetime,
'number_of_units': 0
} for component in get_components])
return self.render_to_response(
{'product_component_formset': formset,
'product_list': product_list,
})
def post(self, *args, **kwargs):
formset = RequestFormset(data=self.request.POST)
if formset.is_valid():
for form in formset:
form.save()
return super().form_valid(form)
formset.html
{% for product in product_list %}
<input class="filterbox" type="checkbox" name="interest" value="{{product.title}}" />{{product.title}}<br />
{% endfor %}
<form method="post">
{% csrf_token %}
<table class="table table-hover" style="border-color: 1px solid black !important;">
{{ product_component_formset.management_form }}
<thead>
<th>Product</th>
<th>Component</th>
<th>Number of units</th>
</thead>
<tbody>
{% for form in product_component_formset.forms %}
<tr class="{% cycle 'row1' 'row2' %} formset_row hidden tags test-" style="border-color: black">
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<button class="cost-calculator" type="submit">Submit</button>
</form>
{% block javascript_files %}
<script>
$('input').click( function() {
$('.tags').hide();
$('input:checked').each( function(i) {
$('tbody tr').show();
});
});
</script>
{% endblock javascript_files %}
Maybe a script like this could help?
Edit: this do update the html only, if you are using some sort of automated form submiting all rows data, you may want to filter by only those being shown, for example using a css class to declare wheter or not a row is aviable to submition.
$('.tags').hide();
$('.control').find('input:checkbox').each(function() {
$(this).click(function(){
$('input:checkbox').each( function() {
checked = $(this).prop('checked');
if(checked) $('div#' + $(this).val()).show();
else $('div#' + $(this).val()).hide();
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="control">
<input type="checkbox" value="generated_1"> <label>show/hide generated_1 </label>
<input type="checkbox" value="generated_2"> <label>show/hide generated_2 </label>
<input type="checkbox" value="generated_3"> <label>show/hide generated_3 </label>
</div>
<ul>
<li>
<div class="tags" id="generated_1">Generated row 1</div>
</li>
<li>
<div class="tags" id="generated_2">Generated row 2</div>
</li>
<li>
<div class="tags" id="generated_3">Generated row 3</div>
</li>
</ul>
In django it would be something like this:
{% for item in list %}
//if statement to prevent not desired filter checkboxes being generated
<input type="checkbox" value="{{item.field_name_for_example}}"> <label>show/hide {{item.field_name_for_example}}</label>
{% endfor %}
<ul>
{% for item in list %}
<li>
<div class="tags" id="{{item.field_name_for_example}}">Generated row 1</div>
</li>
{% endfor %}
</ul>
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>
The voting proceess is working fine with this code. The problem is only when redirecting after voting the options.
Exception Type:DoesNotExist
Exception Value:
Category matching query does not exist.
category = Category.objects.get(slug=slug)
urls.py
path('<slug>/',views.options,name='options'),
path('<slug>/vote/', views.vote, name='vote'),
views.py
def home(request):
categories = Category.objects.filter(active=True)
return render(request,'rank/base.html',{'categories': categories,'title':'TheRanker'})
def options(request,slug):
category = Category.objects.get(slug=slug)
options = Option.objects.filter(category=category)
return render(request,'rank/options.html',{'options':options,'title':'options'})
def vote(request,slug):
option = Option.objects.get(slug=slug)
if Vote.objects.filter(slug=slug,voter_id=request.user.id).exists():
messages.error(request,'You Already Voted!')
return redirect('rank:options',slug)
else:
option.votes += 1
option.save()
voter = Vote(voter=request.user,option=option)
voter.save()
messages.success(request,'Voted!')
return redirect('rank:options',slug)
options.html
{% extends "rank/base.html" %}
<title>{% block title %}{{title}}{% endblock title%}</title>
{% load bootstrap4 %}
{% block content %}
<center><br>
<center>{% bootstrap_messages %}</center>
<ol type="1">
{% for option in options %}
<div class="col-lg-6 col-md-6 mb-6">
<div class="card h-100">
<div class="card-body">
<b><li>
<img src="/media/{{option.image}}" width="200" height="100">
<h4>{{option.name}}
</h4>
<h5 class="card-text">{{ option.details}}</h5>
<h5>{{ option.votes }} votes</h5>
<form action="{% url 'rank:vote' option.slug %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-success" value="Vote" >
</form>
</li></b>
</div>
<div class="card-footer">
<small class="text-muted"></small>
</div>
</div>
</div>
{% endfor %}
</ol>
</center>
{% endblock content%}
You're confusing categories and options. The form sends the slug of the option, but then you redirect to the categories view using the same slug. But those are two different models.
I am getting no value on request in flask. It is returning None value.
I have tried changing the method but no use.
The flask code:
#app.route("/login/user/book")
def searchbook():
bookname=request.form.get("search")
return render_template("message.html",heading=bookname ,message=" ")
The webpage:
{% extends "layout.html" %}
{% block heading %}Welcome to BookSarkar{% endblock %}
{% block body %}
<p>Welcome {{ name }}</p>
<form action="{{ url_for('searchbook') }}" method="get" class="form-group">
<div class="form-group">
<input type="text" name="search" class="form-control col-md-6 mt-5 mx-auto" placeholder="Search books">
<p style="text-align:center;">
<button type ="submit" class="btn btn-primary mt-2 mx-auto">Search</button>
</p>
</div>
</form>
<div class="fixed-top m-2">
<a class="btn btn-outline-primary" href="{{ url_for('logout') }}" role="button" style="float:right;">Log out</a>
</div>
{% endblock %}
The message webpage:
{% extends "layout.html" %}
{% block heading %}{{ heading }}{% endblock %}
{% block body %}
{{ message }}
<a class="btn btn-primary" href="{{ url_for('index') }}" role="button">Return to Home Page</a>
{% endblock %}
The layout page has no bugs as all other pages are working fine. I expected the webpage to show the given input but it is showing None
request.form contains values submitted via post or put, while your form uses get. Try using request.args.get("search") instead of request.form.get("search")
I'm Creating Small Size of Web Interface.I created the edit button in Web Interface.But ,it's not working.It Creating as a new Entry in Database.Can anyone help me.One more thing is How to retrieve the values from database while editing existing values.Thanks for advanced.
Here is The Python Code:
class UserForm(FlaskForm):
type=StringField('type')
#app.route('/newuser', methods=['GET', 'POST'])
def add_user():
form = UserForm()
if form.validate_on_submit():
user_details = {
'type': form.type.data
}
sqlsession.add(user_details)
return redirect(url_for('vehicle_type'))
return render_template('vehicletype.html', form=form)
#app.route('/control/edit/<int:id>',methods=['POST','GET'])
def edit(id):
qry=sqlsession.query(Vehicletype).filter(Vehicletype.id==id).first()
form = UserForm(request.form, object=qry)
if form.validate_on_submit():
form.populate_obj(qry)
sqlsession.update(qry)
sqlsession.commit()
return redirect(url_for('vehicle_type'))
return render_template('vehicletype.html', form=form)
Here is the Templates of the vehicletype.html Code:
{% 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><!--/.row-->
<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 vehicletypedetails.html code:
{% 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 %}
I have been trying to solve this issue for 6 days .But I Could not find any solution. Please could you help me anyone.
Your code to edit an existing entry has a route of /control/edit/<int:id>, but your form you're using to submit the user-changes is pointing at a different route located at /post/vehicletype.
You'll need to change your return from:
return render_template('vehicletype.html', form=form)
to:
return render_template('vehicletype.html', form=form, car_id=id)
And then change your html code from:
<form role="form" action="/post/vehicletype" method="post">
to:
<form role="form" action="{{ url_for('edit', id=car_id) }}" method="post">
With that in place, your form code will be getting submitted to the correct route for processing.