Django search functionality - python

I added a search functionality to my website, such that if you goto www.mywebsite.com/search/texthere , it displays all the songs with title=texthere. I would like to add this functionality to my index page.
In my page, there is an input box where users could type the input and the press submit to submit the input but it goes to some another page.
How can I solve this?
urls.py
url(r'^search/(?P<query>[\w\-]+)/$', views.search, name='search'),
index.html
<form action="/search/">
<input type="text" name="query" value="me"><br>
<input type = "submit">
</form>
What I want is when the user clicks submit button, the text from the input box should be used as the query in urls.py Any help would be appreciated. Thanks!

I think you can get this work by using redirect.
Add a url for /search/ endpoint in your form:
url(r'^search/$', views.search_redirect),
In the views:
def search_redirect(request):
query = request.POST.get('query', '')
return redirect('/search/{}/'.format(query))
the form in your index.html should use method 'POST':
<form action="/search/" method="POST">
<input type="text" name="query" value="me"><br>
<input type = "submit">
</form>
When you submit the query string, search_redirect function get the query string and redirects the request to your /search/<query>/ function.
Hope this will help.

EDIT: Your current search url needs query value also to be passed. But in form action only /search/ is there. During the form submission query value will be passed in request.POST and you wont be able to pass the the query value directly in the url like this /search/sample_query
You need to add one more url:
url(r'^search/$', views.search, name='search'),
And in views:
def search(request, query_via_url=false):
# if form submission is true
if request.post:
query_via_form = request.post.get('query', '')
...
# if query value is passed directly via url
if query_via_url:
....

Related

Django HttpResponseRedirectwith URL Variables handling

I created an input form to get the data into web and use the inputs for an AP call.
When I want t refresh the page, there is a popup asking if you want to refresh the input. This is very annoying.
The solution was to use HttpResponseRedirect, which workout nicely, but it's throwing away all the inputs. Then the though would be to use variable in the URL with "URL?rds=2".
How do you get the input variables through the HttpResponseRedirect to the same site?
And also how to get variables from URL to input and from input to the URL?
HTML input definition:
<form action="{% url 'page' %}" method="post">
{% csrf_token %}
<input type="number" value="{{request.GET.rds}}" name='rds'>
<input type="submit" value="Search">
</form>
views.py:
Getting the data from the URL input
if 'rds' in request.GET.keys():
radius = request.GET.get('rds')
else:
request.GET.rds = '3'
radius = '3'
Redirecting input if user pressed. Add more variables with "&" if needed.
if request.method == 'POST':
radius = request.POST.get('rds')
redirect_link = request.path_info + '?rds=' + str(radius)
return HttpResponseRedirect(redirect_link)
This will redirect the radius to the same page and will put rds as a get attribute, which will be fatched by the if method.
Afterwards you can use the data with.
context = {'radius': radius}
return render(request=request, template_name='realestate/page.html', context = context)
I hope this is helpfull. Maybe there is also a way better solution then this.

Django Edit Form Creates New Instance

I am creating a form that allows users to edit an event saved to a django database. The problem is when it runs the code, a new instance is created in the database, the old one remains in the database and both are then available to view in the site
Below is (some of) the HTML form that is used to call the edit view and edit the instance in the database
<div class="modal-footer">
<form action="edit/" method="POST">
{% csrf_token %}
<input type="hidden" name="event_edit_id" id="event_edit_id">
<input class="btn btn-primary btn-block" type="submit" value="Save Changes"/>
</form>
</div>
Next, is the View that is used to edit the event for the id sent with the form:
def edit(request):
if request.method == "POST":
event_id = int(request.POST.get('event_edit_id'))
event = Events.objects.get(pk=event_id)
form = AddEventForm(request.POST or None, instance=event)
if form.is_valid():
form.save()
return redirect('calendar')
I know I am missing something but I just can't see it, any help appreciated!
EDIT
I've noticed that when the code is submitted for edit, it goes straight to /calendar/ instead of /calendar/edit so this is the urls file I use to map the files
urlpatterns = [
path('', views.calendar, name="calendar"),
path('delete/', views.delete, name="delete"),
path('edit/', views.edit, name="edit"),
]
Without seeing your form, I can only guess that there's nothing populating edit_event_id, so the form is saved as a new event. Currently, edit_event_id isn't a bound field, so it doesn't contain any data.
Ok so I got it, and it was impossible for anyone else to get it because the issue was further up in the code than in the I had included in the html.
My error was that I had not changed the code properly after a previous edit. There was another form that was open and I didn't delete the start of the form tag..
Basically, I didn't make sure the HTML tags each had an opening and closing tag.
On this is correct, the code above will work to edit entries :)

Django 1.10 : view function() takes exactly 2 arguments (1 given)

This is my first django project and I'm struggling to finish it.
I've been working to function that editing post. When user clicks button, it send no(int)for that article, and get information related to no and display on page. User can edit that post in the same form and when user click submit, it redirect to home.html
However, the function I made keep sending me an error message that it takes 2 arguments even though I did not use any function that takes 2 arguments.
Here is views.py
#login_required
def edit_article(request, article_no):
article = Article.objects.filter(pk=article_no)
form = ArticleForm(request.POST, instance=request.article)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, _('Article correctly saved.'))
# If the save was successful, redirect to another page
redirect_url = reverse('blog/home.html')
return HttpResponseRedirect(redirect_url)
else:
form = ArticleForm(instance=request.article)
return (request, {'form': form}, context)
This is form in detail.html where send no value to edit_article.html
<form action="{% url 'blog:edit_article' %}" method="post" style="display: inline;">
{% csrf_token %}
<input type="hidden" name="no" value="{{ item.no }}" />
<button type="submit">edit></button>
</form>
The article_no arg does not magically find its way into the function call via the POST submit. You need to provide it to the url tag:
{% url 'blog:edit_article' item.no %}
This assumes, of course, that you have a url pattern with an appropriate named group associated with this view/view name.
If You are talking about this function, it does recieve more than one Arg, it recieves the No you are talking about, and the request object
def edit_article(request, article_no):
...
If your view needs arguments you must give the arguments in the url templatetag, like this :
{% url 'accounts:detail_account' username = username %}

Django render different templates for two submit buttons in a form

I am a beginner at Django development, and I am trying to make a food diary application. After a user enters his email on index.html, another web page should be rendered according to whichever button he clicks.
I can possibly add two templates, but I also want my app to work if a user manually types a valid URL such as /apps/<user_email>/addDiaryEntry/. I don't know what to add in /apps/urls.py. Also, can I somehow access a user object's Id so my routing URL become /apps/<user_id>/addDiaryEntry/ instead?
/templates/apps/index.html
<form method="post" action="/apps/">
{% csrf_token %}
<label for="email_add">Email address</label>
<input id="email_add" type="text">
<button type="submit" name="add_entry">Add entry</button>
<button type="submit" name="see_history">See history</button>
/apps/views.py
def index(request):
if request.POST:
if 'add_entry' in request.POST:
addDiaryEntry(request)
elif 'see_history' in request.POST:
seeHistory(request)
return render(request, 'apps/index.html');
def addDiaryEntry(request):
print ("Add entry")
def seeHistory(request):
print ("See history")
/apps/urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
]
Thank you for your help! Please feel free to share any best practices which I am not following.
1) passing in an argument into a url, you can use regex groups to pass arguments. Here is an example using a kwarg:
url(r'^(?P<user_email>[^#]+#[^#]+\.[^#]+)/addDiaryEntry/$', views.add_diary, name='add-diary-entry'),
2) just render a different template depending on which button was pressed:
def index(request):
if request.POST:
if 'add_entry' in request.POST:
addDiaryEntry(request)
return render(request, 'apps/add_entry.html');
elif 'see_history' in request.POST:
seeHistory(request)
return render(request, 'apps/see_history.html');
It's always tough starting out, make sure you put in the time to go over the docs, here are some places to look over regarding these topics:
https://docs.djangoproject.com/en/1.10/topics/http/urls/#named-groups
https://docs.djangoproject.com/en/1.10/topics/http/views/

How to post to a view in django from a django template?

Heres the scenario:
I have a email subscriber/un-subscriber app. I am stuck up in the un-subscribing a user part. The user is given a link, which if he/she follows will be able to un-subscribe. The link is typically a view, in the following format:
r^'/unsub_view/(?P<user_id>\w+)/$'
So, when the user follows this links he/she is doing a GET request on the view unsub_view with a parameter user_id. So I have coded up my view as:
def unsub_view(request, user_id):
if request.method == 'GET':
### Do some DB lookup to determine if it is a valid user or not
if user_is_valid:
return direct_to_template(request, '/app/unsub.html', {'user': user})
Now when a valid user is doing the GET, a confirmation dialogue is shown, along with a button. If he/she clicks on the button, I want the template to post the 'user' to the same view, thus the unsub_view also has this piece of code:
if request.method == 'POST':
if user_is_subscribed:
#Unsubscribe the user.
else:
#Show error meessage.
My question is how can I have the button in my template to post to this view ? I have looked around but I got POST-ing to a .php or .asp
Please help.
Note: If there is a better workflow idea, I am also open to that, so please do suggest if there is one.
In the template unsub.html rendering the form with the button, you should pass the url of your view using the reverse method
from django.code.urlresolvers import reverse
def unsub_view(request, viewid):
if request.method == 'POST':
if user_is_subscribed:
#Unsubscribe the user.
submit_url = reverse('unsub_view', viewid)
return direct_to_template(request, '/app/unsub.html', {'user': user, 'submit_url'})
else:
#Show error meessage.
in your template you can then render the form like follows :
...
<form method='post' action='{{ submit_url }}'>
{% csrf_token %}
<input type="hidden" value="{{ user_id }}" name="user_id" />
<input type="submit" value="unsubscribe"/>
</form>
...
Django also has a full framework dedicated to form modeling and rendering. You could take advantage of that to generate the form.

Categories

Resources