Render Template FLASK - html

I have a problem with reload page, when I click the button wchich is used to filtrate data witch using ajax script. In condition IF not working render template .
Below sample code
Python
def viewchallenges():
categories = Categories.query.all()
if request.method=='POST':
category_id=Categories.query.filter_by(category=request.form['name']).first()
check=Challenge.query.filter_by(categorie_id=category_id.id).order_by(Challenge.timestamp.desc()).all()
if not check:
flash(_('not found'))
else:
page = request.args.get('page', 1, type=int)
posts = Challenge.query.filter_by(categorie_id=category_id.id).order_by(Challenge.timestamp.desc()).paginate(
page, current_app.config['POSTS_PER_PAGE'], False)
next_url = url_for('main.viewchallenges', page=posts.next_num) \
if posts.has_next else None
prev_url = url_for('main.viewchallenges', page=posts.prev_num) \
if posts.has_prev else None
return render_template('viewChallanges.html', title=_('View Challenge'), posts=posts.items, next_url=next_url, prev_url=prev_url,categories=categories)
page = request.args.get('page', 1, type=int)
posts =Challenge.query.order_by(Challenge.timestamp.desc()).paginate(
page,current_app.config['POSTS_PER_PAGE'], False)
next_url = url_for('main.viewchallenges', page=posts.next_num) \
if posts.has_next else None
prev_url = url_for('main.viewchallenges', page=posts.prev_num) \
if posts.has_prev else None
return render_template('viewChallanges.html', title=_('View Challenge'), posts=posts.items, next_url=next_url, prev_url=prev_url,categories=categories)
HTML
{% for item_category in categories %}
<button class="btn btn-secondary fby_category">{{item_category.category}}</button>
{% endfor %}
AJAX
$('.fby_category').click(function(e) {
var url = "{{ url_for('main.viewchallenges') }}";
e.preventDefault();
$.ajax({
type: "POST",
url: url,
data: {
'name': $(this).text()
},
});
});

You want to render a new template. It means that the user is going to get a new webpage. Then you do not need Javascript here. You can just create multiple forms
{% for item_category in categories %}
<form action="{{ url_for('main.viewchallenges') }}" method="post">
<input type="submit" name="{{item_category.category}}<" value="
{{item_category.category}}" />
{% endfor %}
</form>
Easier, isn't ?

Related

django-filters form not showing(only the submit button does)

template
<form method="get">
{{ filter.form.as_p }}
<input type="submit" value="Press" />
</form>
{% for obj in filter.qs %}
{{ obj.WorkType }} - ${{ obj.desired_wage }}<br />
{% endfor %}
views
#login_required(login_url='login')
def ListingsPage(request):
review = Review.objects.all()
filter = Profilefilter(request.GET, queryset=Profile.objects.all())
context = {"profile":profile,"review":review,"filter":filter}
return render(request,"base/Listings.html",context)
filters.py
import django_filters
from .models import Profile
class Profilefilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='iexact')
class Meta:
model = Profile
fields = ['WorkType', 'gender']
urls.py
urlpatterns = [
path('Listings/', views.ProfileSearch, name='profile_search_bar'),
path('',views.hello,name="home"),
path('Listings/', views.ListingsPage,name="listings"),
It is supposed to be showing the filters but doesn't render anything, only the submit button shows up. I think it is something to do with passing the context, not sure tho
You need to add qs for query filter
def ListingsPage(request):
review = Review.objects.all()
filter = Profilefilter(request.GET, queryset=Profile.objects.all())
review = filter.qs
context = {"profile":profile,"review":review,"filter":filter}
return render(request,"base/Listings.html",context)

How can I get post id from my html form to views.py

I am using Django, jQuery and Ajax. But, I am confused about how I can get the post id in ajax data to use that in views.py. I am adding code here and must read comments in the code so you can understand better what i am actually trying to explain or what problem I am facing. If this question require your little bit more time than answering other questions than please do not skip this question if you know the solution. All i can do for you is that i can up vote you 10 to 15 answers so that your reputation can increase.
I am beginner with JQuery so please explain your answer briefly.
So ,Here down below i have div tag which will provide me post id. if user click on the reply button.
<div id='post_id' post="{{post.id}}">
{% if node.level < 3 %}
<button class='btn btn-success' onclick="myFunction({{node.id}})">Reply</button>
{% endif %}
</div>
Than I have also form for comment.
<form id='commentform' class='commentform' method='POST'>
{% csrf_token %}
{% with allcomments as total_comments %}
<p>{{ total_comments }} comment{{total_comments|pluralize}}</p>
{% endwith %}
<select name='post' class='d-none' id='id_post'>
<option value="{{ post.id }}" selected="{{ post.id }}"></option>
</select>
<label class='small font-weight-bold'>{{comment_form.parent.label}}</label>
{{comment_form.parent}}
<div class='d-flex'>
<img class='avatar_comment align-self-center' src="{% for data in avatar %}{{data.avatar.url}}{%endfor%}">
{{comment_form.body }}
</div>
<div class='d-flex flex-row-reverse'>
<button type='submit' class='newcomment btn btn-primary' value='commentform' id='newcomment'>Submit</button>
</div>
</form>
between script tags I have set an event which is linked with form.
$(document).on('click', '#newcomment, #newcommentinner', function (e) {
e.preventDefault();
var button = $(this).attr("value");
var post_id = document.getElementById('post_id').getAttribute('post'); #Here I am trying to take post id from div tag with id='post_id'.
console.log(post_id,'postid') #In console it is returning me 2 which is right post id.
var placement = "commentform"
if (button == "newcommentform") {
var placement = "newcommentform"
}
$.ajax({
type: 'POST',
url: '{% url "posts:addcomment" pk=post.pk slug=post.slug %}',
data: $("#" + button).serialize() + {'post_id' : post_id},#Here I am trying to take that post id in data so i can use that in views.py. But in views.py it is returning me none And I don't understand why ? Because this is a post_id variable which is returning me 2 in console but in terminal it is returning me none. Please tell me how can i fix it.
cache: false,
success: function (json) {
console.log(json)
$('<div id="" class="my-2 p-2" style="border: 1px solid grey"> \
<div class="d-flex justify-content-between">By ' + json['user'] + '<div></div>Posted: Just now!</div> \
<div>' + json['result2'] + '</div> \
<hr> \
</div>').insertBefore('#' + placement);
$('.commentform').trigger("reset");
formExit()
},
error: function (xhr, errmsg, err) {
}
});
})
If more information is require than tell me. I will update my question with that information.
in console:
in terminal:
it worked for me.
data: $("#" + button).serialize() +"&post_id="+post_id

how to pass value from html to view in django?

I have made this HTML code:
<h3>your major is {{user.userprofile.major}}</h3>
This will correctly show the major on the webpage, but I want to use this string to get something from another table in view.
How would I pass this string to view?
edit:
Here is my view.py
def dashboardView(request):
obj = BooksFile.objects.all()
query = BooksFile.objects.filter(book_major='cs)
return render(request, 'dashboard.html', {'books': obj, 'major': query})
def registerView(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return redirect('login_url')
else:
form = UserCreationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form': profile_form}
return render(request, 'registration/register.html', context)
here is my template:
{% extends 'index.html' %}
{% block content %}
<h1>Welcome, {{user.username}}</h1>
<h2>Your major is {{user.userprofile.major}}</h2>
{% for book in books %}
<h3>Your book name is {{book.book_name}}</h3>
{% endfor %}
{% endblock %}
I am trying to show the book names from the booksfile table by corresponding major that user has. Right its showing the books that has "cs" attribute because I manually put "cs" in the get function in view. I am trying to send the major string from template to view, so that I can put what ever the user's major is in the get function. Or is there any other way to do it.
You need to use a form in your template and submit it to call your view. i.e.
<form action="your_view_url" method="POST">
<input type="text" name="major" value="{{user.userprofile.major}}"/>
<input type="submit"/>
</form>
an then in your view you access that with:
if request.POST:
major = request.POST.get('major')
As per documentation: https://docs.djangoproject.com/en/2.2/topics/forms/
First of all you have to get the value of model with help of queryset, and put it in the dictionary and then pass it with the template.
In views:
def get(self, request):
queryset = Model_name.objects.all()
ctx = {
'queryset': queryset,
}
return render(request, 'page_name(or template_name).html', ctx)
in template:
<form action="{%url'(your_view_name without brackets)'%}" method="POST">
{% for data in queryset%}
<span class="username">{{data.name(field of your model)}} .
</span>
<span class="email">{{data.email(field of your model)}} .
</span>
{% endfor%}
</form>

Edit data in a form

I've been able to use a django form and template to insert data to the database. I can also display the data in a very basic HTML page. However, am completely unable to figure out how I go about editing the data. Am assuming that I can at least reuse the django template I used to create a new database entry to also edit the entries thus eliminating the need to create an "edit" template.
Mind you I can edit the entry in console but in the browser I just can't seem to get my head around to how to load the data, which variables carry my primary key when I click on a link of a displayed vehicle and how to pass the fetched data from the database to the form to allow for editing etc. I've checked the admin site for guidance on how it does it on that end but still.... no luck.
Here is my insert code: How do I modify this to allow me to edit the data displayed by the vehicle.html further below?
views.py
vehicle_add - inserts to database
def vehicle_add(request):
if request.method == 'POST':
form = VehicleForm(request.POST)
if form.is_valid():
newvehicle = Vehicle()
vdetails = form.cleaned_data
newvehicle.reg_number= vdetails['regnumber']
newvehicle.model= vdetails['model']
newvehicle.manufacturer= vdetails['manufacturer']
newvehicle.year= vdetails['year']
newvehicle.chassis_number= vdetails['chasisnumber']
Vehicle.save(newvehicle)
return HttpResponseRedirect('/vehicle')
else:
form = VehicleForm()
return render_to_response('vehicle_add.html', {'form': form}, context_instance=RequestContext(request))
The vehicle.html loads the data in a simple HTML format as below:
{% for v in obj %}
<tr><td>{{ v }}</td></tr>
{% endfor %}
The link is displayed like this: http://localhost:8000/vehicle_add/2/
More Info:
vehicle_add.html
{% extends "base.html" %}
{% block title %}Add Vehicle{% endblock %}
{% block page %}Add Vehicle{% endblock %}
{% block content %}
<html>
<head>
<style type="text/css">
ul.errorlist {
margin: 0;
padding: 0;}
.errorlist li {
background-color: red;
color: white;
display: block;
font-size: 10px;
margin: 0 0 3px;
padding: 4px 5px;}
</style>
</head>
<body>
<section id = "mainform">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">{% csrf_token %}
<div class="field">
{{ form.regnumber.errors }}
<label for="id_regnumber">Reg #:</label>
{{ form.regnumber }}</div>
<div class="field">
{{ form.model.errors }}
<label for="id_model">Model:</label>
{{ form.model }}</div>
<div class="field">
{{ form.manufacturer.errors }}
<label for="id_manufacturer">Manufacturer:</label>
{{ form.manufacturer }}</div>
<div class="field">
{{ form.year.errors }}
<label for="id_year">Year:</label>
{{ form.year }}</div>
<div class="field">
{{ form.chasisnumber.errors }}
<label for="id_chasisnumber">Chasis #:</label>
{{ form.chasisnumber }}</div>
<div class="field">
<input type="submit" value="Submit">
<input type="submit" value="Clear">
</div></form></section>
</body>
</html>
{% endblock %}
Trial and Error:
This is what I've tried to do with my view but with no luck:
def vehicle_add(request):
if request.method == 'POST':
form = VehicleForm(request.POST)
if form.is_valid():
newvehicle = Vehicle()
vdetails = form.cleaned_data
newvehicle.reg_number= vdetails['regnumber']
newvehicle.model= vdetails['model']
newvehicle.manufacturer= vdetails['manufacturer']
newvehicle.year= vdetails['year']
newvehicle.chassis_number= vdetails['chasisnumber']
Vehicle.save(newvehicle)
return HttpResponseRedirect('/vehicle')
else:
#WORKING ON THIS
form = VehicleForm
newvehicle = Vehicle.objects.get(pk=9)
form = VehicleForm(newvehicle)
return render_to_response('vehicle_add.html', {'form': form}, context_instance=RequestContext(request))
But on doing so I get different type of errors. Am not even sure if that is how to do it. Can somebody point me in the right direction?
EDIT
Here is the current error:
Caught AttributeError while rendering: 'Vehicle' object has no attribute 'get'
In template d:\dev\workspace\vehicle_request\vehicle_request\mvmanager\templates\vehicle_add.html, error at line 31
It then highligths this part of the template: {{ form.regnumber }}
forms.py
class VehicleForm(forms.Form):
regnumber = forms.CharField(
max_length=7,
label='Reg #:',
widget = forms.TextInput(attrs={'size':7}) )
model = forms.CharField(
label='Model',
widget = forms.TextInput(attrs={'size':25}) )
manufacturer = forms.CharField(
max_length=25,
label='Manufacturer',
widget = forms.TextInput(attrs={'size':25}) )
year = forms.IntegerField(
label='Year',
widget = forms.TextInput(attrs={'size':4}) )
chasisnumber = forms.CharField(
required=False, label='Chasis #',
widget = forms.TextInput(attrs={'size':25}) )
Modify url conf line to use parameters in url,
e.g.:
(r'^vehicle_add/(\d+)/$','app.views.vehicle_add')
In vehicle_add first parameter (second after self parameter) will be vehicle_id taken from url.
You can name it as you wish,
e.g. vehicle_id.
Use it :
newvehicle= Vehicle.objects.get(pk=vehicle_id)
Pass the form a dict:
#WORKING ON THIS
# form = VehicleForm <<< THIS LINE IS UNNECESSARY
newvehicle = Vehicle.objects.get(pk=9)
form = VehicleForm(newvehicle.__dict__)

HTML input textbox in Django admin.py filter

I would like to filter data in Django (admin.py) with text writen in HTML input textbox. I need to filter companies by city in which they are and list of all cities is too long. I would like to replace list of all cities in filter by one text input. I found something similar
here http://djangosnippets.org/snippets/2429/ but there are two problems:
author did not posted models.py, so it is difficuilt to change code for my needs (+ no comments)
there is used class UserFieldFilterSpec(RelatedFilterSpec): but I need to use AllValuesFilterSpec instead of RelatedFilterSpec (more in file django/contrib/admin/filterspecs.py), because list of towns are in the same class as comapny (there shoud by class of towns and they should be referencing to company by foreign key (ManyToMany relationship), but for some reasons it have to be done this way)
important part of models.py looks something like this
class Company(models.Model):
title = models.CharField(max_length=150,blank=False)
city = models.CharField(max_length=50,blank=True)
and something from admin.py
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = ['city',]
So again, I need to:
1. instead of list od cities display one text input in Django filter
2. After inputing city neme in that text input, filter data by city (request for filtering can be sent with some submit button or through javascript)
Thank yoy for all posts.
In case anybody still need this. It is little hackish in template, but implemented without a piece of js.
filters.py:
from django.contrib.admin import ListFilter
from django.core.exceptions import ImproperlyConfigured
class SingleTextInputFilter(ListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, request, params, model, model_admin):
super(SingleTextInputFilter, self).__init__(
request, params, model, model_admin)
if self.parameter_name is None:
raise ImproperlyConfigured(
"The list filter '%s' does not specify "
"a 'parameter_name'." % self.__class__.__name__)
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html:
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Then according to your models in admin.py:
class CatalogCityFilter(SingleTextInputFilter):
title = 'City'
parameter_name = 'city'
def queryset(self, request, queryset):
if self.value():
return queryset.filter(city__iexact=self.value())
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = [CatalogCityFilter,]
Ready to use filter would look like this.
I'm running Django 1.10, 1.11 and r_black's solution didn't completely fit because Django was complaining that filter fields must inherit from 'FieldListFilter'.
So a simple change for the filter to inherit from FieldListFilter took care of Django complaining and not having to specify a new class for each field, both at the same time.
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
if self.value():
return queryset.filter(imei__icontains=self.value())
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html (unchanged):
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Usage:
class MyAdmin(admin.ModelAdmin):
list_display = [your fields]
list_filter = [('field 1', SingleTextInputFilter), ('field 2', SingleTextInputFilter), further fields]
While it's not actually your question, this sounds like a perfect solution for Django-Selectables you can with just a few lines add an AJAX powered CharField Form that will have it's entries selected from the list of cities. Take a look at the samples listed in the link above.
Below is the fix for field name..in queryset function
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
variable_column = self.parameter_name
search_type = 'icontains'
filter = variable_column + '__' + search_type
if self.value():
return queryset.filter(**{filter: self.value()})
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': ('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )