get_query_set(self) is not being called in django - django

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.

Related

How to search for exact values in Django?

I have created a search function. However, it searches for all elements that contain the entered value. For example, there are the following elements: 44564, 76436, 445. When I enter "445", it shows "44564" and "445", but I need only 445. Or if I enter "64", then nothing should be shown, but "44564" and "76436" are shown. How to fix it?
case_list.html
<div>
<h3>Search</h3>
<form method="GET" action="{% url 'case_search' %}">
<input type="search" type="text" name="q" prequired placeholder="Put value">
<button type="submit">Find</button>
</form>
</div>
<div>
{% for case in object_list %}
<div>
<p>{{ case.name }}</p>
</div>
{% endfor %}
</div>
Views.py
class CaseView(ListView):
model = Case
template_name = 'case_list.html'
class CaseSearch(ListView):
template_name = 'case_list.html'
def get_queryset(self):
return Case.objects.filter(name__icontains=self.request.GET.get("q"))
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context["q"] = self.request.GET.get("q")
return context
Urls.py
path('case_list/', CaseView.as_view(), name='case_list'),
path('case_list/search/', CaseSearch.as_view(), name="case_search"),
Use iexact for exact matches. Check out the docs https://docs.djangoproject.com/en/4.1/ref/models/querysets/#iexact
Case.objects.filter(name__iexact=self.request.GET.get("q"))

How to get the value of a specific field in a form in Django view function?

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>

How do you render form from views in template without model?

I have a problem with my Django Code.I'm trying to render a form from views to template and i'm just seeing the submit button. I noticed that we can use forms dynamically by introducing it like this {{ form }}, but when I use it, I just see the "submit" button on the page(Sorry I don't know how to upload a local image here). I join my four files: views.py, home.html, forms.py and urls.py
Thank you in advance
home.html
<form method="POST" novalidate action="/config">
{% csrf_token %}
<fieldset>
<legend class="border-bottom mb-4">Home</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
views.py
def inputHome(request):
form = InputHomeForm()
if request.method == 'POST':
form = InputHomeForm(request.POST)
if form.is_valid():
mk = form.cleaned_data['mk']
return HttpResponseRedirect('blog-config')
else:
form = InputHomeForm()
return render(request, 'blog/home.html', {'form': form})
forms.py
class InputHomeForm(forms.Form):
mk = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
urls.py
urlpatterns = [
path('home/', blog_views.home, name='blog-home'),
]
I don't have an error message so i don't have an idea of the problem.
You are missing form tag in html.
HTML should be,
<form method='post'>
{% csrf_token %}
<fieldset>
<legend class="border-bottom mb-4">Home</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
Slightly unrelated (cf Nishant's answer for the main issue), but here:
if request.method == 'POST':
form = InputHomeForm(request.POST)
if form.is_valid():
mk = form.cleaned_data['mk']
return HttpResponseRedirect('blog-config')
else:
form = InputHomeForm()
In the else clause, you're replacing the bound invalid form (which carries the validation errors) with an unbound form, so you'll never get the error messages. Just remove the whole else clause.

ListView queryset Can not pass context data to Template

I am having trouble with my Search API. Results of the queryset could not get through my template even though the query set fetched data from the model.
If the search is empty the queryset should return all the Models associated to the current project, otherwise, it should return models that qualify the criteria in the query.
I have tested the result of the query and it returns records from the model but could not display the instances into the template.
My SEARCH ListView:
class ModelSearchListView(ListView):
model = Model
template_name = 'predictions/model_listview.html'
context_object_name = 'models'
paginate_by = 2
def get_queryset(self):
query = self.request.GET.get('q')
proj_pk = self.kwargs.get('pk')
proj = get_object_or_404(Project, id=proj_pk)
if query:
result = Model.objects.filter(Q(project=proj.id) & (Q(name__contains=query) |
Q(algorithm_type__contains=query) |
Q(predictors__contains=query) |
Q(target_column__contains=query))).order_by('-date_created')
# print('result: ', result)
else:
result = Model.objects.filter(project=proj.id).order_by('-date_created')
print('result: ', result)
return result
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
project = Project.objects.filter(id=self.kwargs.get('pk')).first()
context['current_project'] = project.id
MY SEARCH FORM:
<form class="form my-2 my-lg-0" method="GET"
action="{% if current_project %}
{% url 'model-search-listview' current_project %}
{% else %}
{% url 'model-search-listview' object.project.id %}
{% endif %}">
<div class="input-group">
<input class="form-control " type="text" name="q" value="{{ request.GET.q }}" aria-label="Search"
placeholder="Search">
<span class="input-group-btn">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit" value="Search">
Search
</button>
</span>
</div>
</form>
The TEMPLATE:
{% if not models %} #Always TRUE because models is empty
<h5>No prediction models created for this project!</h5>
{% else %}
#Loop never executed
{% for model in models %} # models HERE ALWAYS returns empty
[SOME CODE HERE]
{% endfor %}
{% endif %}
You need to return the new context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
project = Project.objects.filter(id=self.kwargs.get('pk')).first()
context['current_project'] = project.id
return context

passing form arguments in django

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