I am trying to implement a simple search function in django but somehow I can't pass the argument from my template to my view function. I've got a key error: KeyError at /artdb/search/ because kwargs is empty:
url.py:
path('search/',views.Search.as_view(),name='search'),
base,.html:
<form class="form-inline my-2 my-lg-0" name="search" action="{% url 'artdb:search' %}" {{ form.as_p }} method="get">{% csrf_token %}
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search" value="{{seastr}}">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit" value="{{seastr}}">Search</button>
</form>
views.py:
class Search(ListView):
print("class Search")
model=Person
template_name='artdb/search.html'
context_object_name='ans'
def get_queryset(self):
Pdb().set_trace()
self.seastr=get_object_or_404(Person,name=self.kwargs['seastr'])
return Person.objects.filter(seastr=self.seastr)
You did not attach the name seastr to your <input> field:
<form class="form-inline my-2 my-lg-0" name="search" action="{% url 'artdb:search' %}" {{ form.as_p }} method="get">{% csrf_token %}
<input name="seastr" class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search" value="{{seastr}}">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
Notice the name="seastr" in the <input> tag.
GET parameters are not stored in self.kwargs, but in self.request.GET, so we can obtain the parameter with self.request.GET['seastr'].
Typically the page with the search bar, is the same as the one with the request, therefore the search request if frequently optional. So it might be useful to make filtering optional here:
class Search(ListView):
model=Person
template_name='artdb/search.html'
context_object_name='ans'
def get_queryset(self):
q = self.request.GET.get('seastr')
if q is not None:
return Person.objects.filter(seastr=q)
else:
return Person.objects.all()
Finally note that the seastr parameter is not part of the context data. You can make this part of the context data, by patching it:
class Search(ListView):
model=Person
template_name='artdb/search.html'
context_object_name='ans'
def get_queryset(self):
q = self.request.GET.get('seastr')
if q is not None:
return Person.objects.filter(seastr=q)
else:
return Person.objects.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['seastr'] = self.request.GET.get('seastr')
return context
Related
I have a serch field on my page
<form method="GET" class="container mb-5">
<input type="search" class="form-control rounded" placeholder="Write a name" aria-label="Search"
aria-describedby="search-addon" name="search"/>
<button type="submit" class="btn btn-outline-primary px-5" >Search</button>
</form>
And here is my views
def my_view(request):
value_one = request.GET.get("search", None)
objects = MyModel.objects.all()
if value_one:
objects = objects.filter(field_one=value_one)
After I input something in a search field and push the button 'search', text which was in search field dissapears, I want it to stay until the next input. Is it possible to do with Django or not? Don't even know how to google it, everything I found was on different topic
on your template add value to your input:
<form method="GET" class="container mb-5">
<input type="search" class="form-control rounded" placeholder="Write a name" aria-label="Search" value="{{value_one"}}
aria-describedby="search-addon" name="search"/>
<button type="submit" class="btn btn-outline-primary px-5" >Search</button>
</form>
and on your view add that value to your context :
def my_view(request):
value_one = request.GET.get("search", None)
objects = MyModel.objects.all()
if value_one:
objects = objects.filter(field_one=value_one)
return render(request,'template.html',{'value_one':value_one,'objects':objects})
Have you heard of django's Form class ? You should be using the Form class to create forms in Django and that would allow you to preserve data between "submit" calls as well as handle errors. Some example code snippets for you:
forms.py
from django import forms
class SearchForm(forms.Form):
search = forms.CharField(label="Search Query", widget=forms.TextInput(attrs={"class": "form-control rounded", "placeholder": "Write a name", "aria-label": "Search", "aria-describedby": "search-addon"}))
views.py
from django.shortcuts import render
from .forms import SearchForm
def my_view(request):
form = SearchForm({"search": request.GET.get("search", None)})
if form.is_valid():
search_query = form.cleaned_data.get("search")
if search_query:
objects = MyModel.objects.filter(field_one=search_query).all()
# ...snip...
return render(request, 'searchform.html', {"form": form})
searchform.html
<form action="{% url 'my_view' %}" method="get">
{{ form }}
<input type="submit" value="Submit" class="btn btn-outline-primary px-5">
</form>
I am trying to achieve a load-up process in my system where the user will input the load amount and add it to a user's current load.
How can I get the amount entered in my view function?
Here's my function in my views.py
def LoadWallet(request, pk):
user = get_object_or_404(User, id=request.POST.get('user_id'))
user_wallet = user.wallet
if request.method == 'POST':
form = LoadForm(request.POST)
if form.is_valid():
user_wallet = user_wallet+form.instance.load_amount
User.objects.filter(id=pk).update(wallet=user_wallet)
return HttpResponseRedirect(reverse('user-details', args=[str(pk)]))
and the form in my template file
<form action="{% url 'load-wallet' user.pk %}" method="POST">
{% csrf_token %}
<label for="load_amount">Load amount</label>
<input type="text" class="form-control" id="load_amount" onkeyup="replaceNoneNumeric('load_amount')">
<button type="submit" name="user_id" value="{{ user.id }}" class="btn btn-md btn-success" style="float: right; margin: 10px 5px;">Load</button>
</form>
Right now I tried this but it's returning "name 'LoadForm' is not defined". Should I declare the LoadForm first?
Is there a better way to implement this? Thank you!
You might have an easier time using something like this, than LoadForm:
def LoadWallet(request, pk):
user = get_object_or_404(User, id=request.POST.get('user_id'))
user_wallet = user.wallet
if request.method == "POST":
user_id = request.POST["user_id"]
# Other logic here
return ...
And in template
<form class="load-wallet" action="" method="POST">
{% csrf_token %}
<input type="text" name="user_id" placeholder="What is the user id?">
<button type="submit" class="submit-btn"> Submit </button>
</form>
I have a search form in my django app. I want to add a filter option and so I'm adding a radio button for filtering by name alphabetically ascending and descending. The value for the search is getting passed through, but the radio button value is
<form method='GET' action='{% url "search:catalog-query" %}' class="form my-2 my-lg-0 search-form">
<div class='input-group'>
<input class="form-control" type="text" placeholder="Search" name='q' aria-label="Search" value='{{ request.GET.q }}'>
<span class='input-group-btn'>
<button class="btn btn-outline-success" type="submit">Search</button>
</span>
</div>
<div>
Sort Name:
<label for="id_sort_up">Ascending</label><input type="radio" name="name_sort" id="id_sort" value='{{ request.GET.name_sort }}'>
<label for="id_sort_down">Descending</label><input type="radio" name="name_sort" id="id_sort" value='{{ request.GET.name_sort }}'>
</div>
</form>
urls.py
url(r'^catalog/$', SearchCatalogView.as_view(), name='catalog-query'),
view.py
class SearchCatalogView(ListView):
template_name = "search/view-catalog.html"
print('search catalog')
def get_context_data(self, *args, **kwargs):
context = super(SearchCatalogView, self).get_context_data(*args, **kwargs)
query = self.request.GET.get('q')
context['query'] = query
return context
def get_queryset(self, *args , **kwargs):
print('get_queryset')
request = self.request
method_dict = request.GET
query = method_dict.get('q', None) # method_dict['q']
print(method_dict)
if query is not None:
return AAAA.objects.search(query)
return AAAA.objects.features()
When I print method_dict, I get <QueryDict: {'q': ['searched_option'], 'name_sort': ['']}> regardless of which radio button I am choosing.
Sort Name:
<label for="id_sort_up">Ascending</label>
<input type="radio" name="name_sort" id="id_sort_up" value='Ascending'>
<label for="id_sort_down">Descending</label>
<input type="radio" name="name_sort" id="id_sort_down" value='Descending'>
would give
method dict <QueryDict: {'q': ['searched_option'], 'name_sort': ['Ascending']}>
or
method dict <QueryDict: {'q': ['searched_option'], 'name_sort': ['Descending']}>
I am implementing search function using TemplateView in Django the class is
class part_search_view(TemplateView):
model = part_list
context_object_name = 'part_list'
template_name = 'part_list.html'
def get_context_data(self, **kwargs):
context = super(part_search_view, self).get_context_data(**kwargs)
context['my_list'] = populate_nav_bar()
return context
def get_queryset(self):
key = self.request.GET['search_text']
partlist = part_list.objects.filter(Q(part_id__icontains=key) | Q(part_name__icontains=key))
return partlist
part_list.html
{% for part in part_list %}
{{ part.part_id }} - {{ part.part_name }}
<a href="{% url 'parts:part_update_view' part.id %}" > Edit </a>
{% endfor %}
the url mapping is
url(r'^search/',views.part_search_view.as_view(),name='part_search_view'),
the form for serch button
<form action="{% url 'parts:part_search_view'%}" role="form" class="navbar-form navbar-left" method="get" >
{% csrf_token %}
<div class="form-group ">
<input class="form-control mr-sm-2" type="text" placeholder="Search" name="search_text">
<button class="form-control search_buton btn btn-success " type="submit" >Search</button>
</div>
</form>
after the search button is pressed the address is
http://127.0.0.1:8000/parts/search/?csrfmiddlewaretoken=PWjEw1hRsyH9B6YcseVuhS0urX8L7f170q9ucLF9hTPQPThulpgMSP4y5xhScCVr&search_text=mp6
but the get_query_set(self) is not called here the get_context_data(...) is called though, why?
TemplateViews don't know anything about querysets, so they never call a get_queryset method. You should subclass a more appropriate view, perhaps ListView.
If you look at docs, TemplateView does not have a method get_queryset(). Then, you would have to manually call it in the view.
Using Django 1.6 with Python 2.7.
My model has a BooleanField variable, and I want the user to be able to change this via POST by clicking a button to change it from False to True, or vice versa. Having issues rendering the template.
Model currently:
class Pic(models.Model):
Name = models.CharField(max_length=100)
Good = models.BooleanField()
Image = models.FileField(upload_to="images/")
def __unicode__(self):
return self.Name
App urls is:
url(r'^(?P<Pic_id>\d+)/$', views.single_picture, name='single_picture'),
In the template I have:
<form action="{% url 'single_picture' Pic.Good %}" method="post">
{% csrf_token %}
{% if Pic.Good %}
<input type="checkbox" name="choice" id="{{ Pic.Good }}" value="False" />
<label for="{{ Pic.Good }}">False</label><br />
{% else %}
<input type="checkbox" name="choice" id="{{ Pic.Good }}" value="True" />
<label for="{{ Pic.Good }}">True</label><br />
{% endif %}
<input type="submit" value="good" />
</form>
And for my view I have:
def single_picture(request, Pic_id):
if request.method == 'GET':
pic = get_object_or_404(Pic, pk=Pic_id)
latest_pictures_list = Pic.objects.all()
return render(request, 'pictures/single_picture.html', {'Pic': pic, 'latest_pictures_list': latest_pictures_list})
elif request.method == 'POST':
pic = get_object_or_404(Pic, pk=Pic_id)
latest_pictures_list = Pic.objects.all()
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Pic.DoesNotExist):
return render(request, 'pictures/single_picture.html', {'Pic': pic, 'error_message': 'uhhhh...',
})
else:
selected_choice.save()
return HttpResponseRedirect(reverse('pictures/single_picture.html', {'Pic': pic}))
I'm not sure if there are multiple errors at this point or not. Currently when trying to view the template, I get
Reverse for 'single_picture' with arguments '(True,)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
for the '< form >' line. I'm guessing it's to do with my View?
I think the issue is in your template, in the line
<form action="{% url 'single_picture' Pic.Good %}" method="post">
Your regex in urls.py is r'^(?P<Pic_id>\d+)/$', I'm guessing that it's expecting the id of the Picobject you return in the GET request and not a boolean, in which case the line should be
<form action="{% url 'single_picture' Pic.id %}" method="post">
Likewise, in the lines underneath, there isid="{{ Pic.Good }}" which will display as HTML as id=True or id=False, which I suppose you don't want. You need to replace that bit by id="{{Pic.id}}"