How does Django urls are matched? - python

I have a page with a form in it. Its url is
url('tasks/searchBook', views.searchBook, name='searchBook'),
when I click the submit button of form, it should go to this url
url('tasks/searchBookResult/', views.searchBookResult, name='searchBookResult'),
Url is changing in address bar but next html file is not rendering.
However if I interchange the place of urls in urls.py file i.e. take the second url on top and first url at bottom then it works fine.
What is happening here?
urls.py file :
urlpatterns = [
url(r'^$', views.index, name='index'),
url('tasks/searchBook/', views.searchBook, name='searchBook'),
url('tasks/searchBookResult/', views.searchBookResult, name='searchBookResult'),
]
form code in template file :
<form action="{% url 'lms:searchBookResult' %}" method="post">
{% csrf_token %}
<div class="inner centerAlign">
<input type="text" id="bookId" name="bookId" placeholder="Book ID" class="inputField"></input>
</div>
<div class="inner centerAlign">
<label>OR</label>
</div>
<div class="inner centerAlign">
<input type="text" id="bookTitle" name="bookTitle" placeholder="Book Title" class="inputField"></input>
</div>
<div class=" inner centerAlign">
<input type="submit" value="Search" class="button button-primary" name="searchBook"></input>
</div>
</form>
views.py :
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index(request):
return render(request, 'lms/loginPage.html')
def searchBook(request):
return render(request,'lms/tasks/searchBook.html')
def searchBookResult(request):
return render(request,'lms/tasks/searchBookResult.html')

Url's are matched as regexes in the order they are shown in the urls.py.
Since searchBook matches before searchBookResult, the first page is returned.
Simply reorder these so searchBookResult url is before the other.
url('tasks/searchBookResult/', views.searchBookResult, name='searchBookResult'),
url('tasks/searchBook/', views.searchBook, name='searchBook'),
Alternatively, you can include a $ at the end of your url which indicates the end of a line
url('tasks/searchBook/$', views.searchBook, name='searchBook'),

Related

Django can't search "method not allowed"

im new to django and im currently doing a website for my friend. he wants me to make a system where the users can search the database and the website gives the relevent items according to their serial number.
i followed a tutorial from the following site: https://learndjango.com/tutorials/django-search-tutorial to figure out how to do db searchs which helped a lot, but im still having a problem: my search bar works, and the result page also works but it only works when i manually type the query on the searchbar myself (e.x. results/?q=number1). However when i search using the input bar and the submit button it sends me to /results/ page and the page gives this:
This page isn’t working
If the problem continues, contact the site owner.
HTTP ERROR 405
-when i open up pycharm to see the error in terminal it says:
Method Not Allowed (POST): /result/
Method Not Allowed: /result/
[27/Oct/2020 20:06:02] "POST /result/ HTTP/1.1" 405 0
here are my codes(python3.7,pycharm) websites/urls:
from . import views
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('register/',views.UserFormView.as_view(), name='register'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('', views.IndexViews.as_view(), name='index'),
path('scan/', views.ScanView.as_view(), name='scan'),
path('result/', views.SearchResultsView.as_view(), name='result'),
]
websites/views:
class IndexViews(generic.ListView):
template_name = "websites/index.html"
context_object_name = "object_list"
def get_queryset(self):
return Website.objects.all()
class ScanView(TemplateView):
form_class = SerialFrom
template_name = 'websites/scan.html'
class SearchResultsView(ListView):
model = SerialNumber
template_name = 'websites/result.html'
def get_queryset(self): # new
query = self.request.GET.get('q')
context = self.get_context_data(object=self.object)
object_list = SerialNumber.objects.filter(
Q(number__iexact=query)
)
return object_list
scan.html:
{% extends 'websites/base.html' %}
{% block albums_active %}active{% endblock %}
{% block body %}
<head>
<meta charset="UTF-8">
<title>Scan</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<form class="box" action="{% url 'result' %}" method="POST">
<h1>Product Check</h1>
<p> Please enter the serial id of your product to check it.</p>
{% csrf_token %}
<input type="text" name="q" placeholder="Serial Number">
<input type="submit" name="q" placeholder="Check">
</form>
</body>
{% endblock %}
thank you for taking your time and reading, please help me i really need to do this.
A ListView [Django-doc] by default does not implement a handler for a POST request. Searching is normally done through a GET request, so you should use:
<form class="box" action="{% url 'result' %}" method="GET">
<h1>Product Check</h1>
<p> Please enter the serial id of your product to check it.</p>
<input type="text" name="q" placeholder="Serial Number">
<input type="submit" placeholder="Check">
</form>
Furthermore the <input type="submit"> should not have a name="q" attribute.
As #Melvyn says, you can also alter the type to type="search" [mozilla] for the text box:
<form class="box" action="{% url 'result' %}" method="GET">
<h1>Product Check</h1>
<p> Please enter the serial id of your product to check it.</p>
<input type="search" name="q" placeholder="Serial Number">
<input type="submit" placeholder="Check">
</form>

Custom url based off single html input without JS

So I have probably the simplest task you could ever wish for with an html form that I cannot solve.
I want to input a brand name into a search bar, click submit and it redirect to the url/brand/[input]
I already have a working view for the urls setup in django. How would I structure the form to actually create my desired url?
<form method="GET" action="">
<input type="text" name="brand" id="brand" placeholder="Search..." aria-label="Search">
<button type="submit">Search</button>
</form>
views.py
class GetByBrand(ListView):
def get(self, request, brand):
urls.py
urlpatterns = [
path('', GetListView.as_view(), name='home'),
path('brands/<str:brand>/', GetByBrand.as_view())
]
<form method="GET" action="brands/">
<input type="text" name="brand" id="brand" placeholder="Search..." aria-label="Search">
<button type="submit">Search</button>
in URLs(import views by from. import views)
urlpatterns = [
path('brands/', views.GetByBrand),
]
in Views
from django.http import HttpResponse
def GetByBrand(request):
s = request.GET['brand']
return HttpResponse(s)
OR use AJAX in Javascript in your HTML file
$('#brand').on('submit',function(e){
var brand = $('input[name=brands]')
$.get("brands/"+brand, function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
})
So I basically solved this by using the code I had previously tried which is identical to what Wagas Develper recommended. What I had not done though was add this last line to the urls.py in the main project folder. (and I'm still not sure why this solved it but found the solution from throwing crap at the wall)
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('shoes.urls')),
path('brands/', include('shoes.urls'))
For anyone curious about how the class based view is structured now.
class GetByBrand(ListView):
def get(self, request, brand):
get_results = request.GET.get('q')
The urls.py in the same directory as views.py (within app dir not main project dir)
urlpatterns = [
path('', GetListView.as_view(), name='home'),
path('brands/<str:brand>/', GetByBrand.as_view()),
path('brand_results/', GetByBrand.as_view(), name='b')
]
HTML Form
<form method="GET" class="form-inline my-2 my-lg-0" action="{% url 'b' %}">
<input class="form-control mr-sm-2 search-btn" type="text" name="q" value="{{request.GET.q}}" placeholder="Search..." aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>

Django: Use text box data and write that text in a file

I am super new to Django and web development. Right now my objective is to create a google like interface and take the text from search box and write it to a file (in other words just want to access text data in the search box). I have created a search page like below
search.html
{% extends "header.html" %}
{% block content %}
<div style="display: flex; justify-content: center;">
<img src="/static/images/logo.jpg" class="responsive-img" style='max-height:300px;' alt="face" >
</div>
<form method="get" action="">
{% csrf_token %}
<div style="display: flex; justify-content: center;">
<input type="text" name="query" placeholder="Search here..." required size="70" >
<button type="submit">Go!</button>
</div>
<button type="submit">Search</button>
</form>
{% endblock %}
views.py
from django.shortcuts import render
def index(request):
return render(request, 'search.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index')
]
Please give me a hint/example of how to go forward from here ? Thanks.
Your search field looks like this:
<input type="text" name="query">
The name of the input is query. Since it's a GET form, when you submit it, you must have noticed, the url looks something like this:
/?query=<value of the input>
The part after ? is called querystring. For every request, Django maintains a dictionary of the querystring. The request object has a dictionary called GET for GET requests. If you make a POST request, Django will save the form data in a dict called POST.
To access the value of the request querystring in Django, you can do this:
query = request.GET.get('query')
If it's a POST request, you'd do the same but use the POST dictionary this time:
some_value = request.POST.get('some_key')
Full docs on this can be found at - Request and response objects.
This should do it
views.py
def index(request):
query = request.GET.get('query')
# do a check here to make sure search_term exists before attempting write
with open('/path/to/file', 'rw') as f:
f.write(query)
return render(request, 'search.html')

Django form not rendering properly

I am following the documentation of the Django Forms but I do not know why my form does not want to show up !
I am creating a form that will get an email en create invitation for user to sign in using this app :https://github.com/bee-keeper/django-invitations
My forms.py:
class InviteForm(forms.Form):
email1 = forms.EmailField(label='Email 1')
My Views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import InviteForm
class candidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
def create_invite(request):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid:
email = form.cleaned_data['email1']
invite = Invitation.create('form.email1')
invite.send_invitation(request)
print("The mail was went")
else:
print("Your form is not valid")
else:
form = InviteForm()
return render(request, 'HRindex.html', {'form': form})
My HTML:
{% extends 'base.html' %}
{% block body %}
<div class="jumbotron">
<h1>Welcome to SoftScores.com</h1>
<h2>Team analytics platfom</h2>
<h3>Welcome to {{user.username}}, it is your Page</h3>
</div>
<div class="container">
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Create a new team
</a>
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
In order to create a new team please invite new members. A link will be sent to them in order to give the access to the application
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
urls.py:
from django.conf.urls import url
from website import views
app_name = 'website'
urlpatterns = [
url(r'^candidateIndex/$', views.candidateIndex.as_view(), name='candidate_index'),
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
]
When it render the page I get only the button but the form does not seems to work
Do you habe any idea ?
You HR_index url is being handled by the HRIndex view, but this does not have any code to handle the form.
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
Since a TemplateView is not really suited to handling a form, it would be better to modify the URL pattern to use the create_invite view instead:
url(r'^HRIndex/$', views.create_invite, name='HR_index'),

how to use ajax to populate Google search result in container on Django

I'm looking to make something like https://www.wolframalpha.com/ except with just vanilla Google. I'd like to have the Google results populate and pop out from the container.
My index will just have something like this:
<form action="search" method="get">
<label for="query">Your Query: </label>
<input id="myapp" type="text" name="myapp" value="Enter your query here">
<input type="submit" value="search">
</form>
</div> <!-- /container -->
</body>
</html>
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
#url(r'^admin/', admin.site.urls),
url(r'^$', include('myapp.urls')),
(r'^search/$', views.search),
]
views.py:
def search(query):
#perform Google search and return the results
return 1
I have a generic setup for non-ajax search as shown above. How would I incorporate ajax here?

Categories