I am creating an app using django where an user can search for definition of some things. So f.e. he is inputing a word "security" to get definition of this. He gets results and then he is pushing back button. And then he gets a website, but the search-field still stores the old data/input "security". How can i fix this?
template:
<div>
<h1>Drink drank drunk</h1>
</div>
<h1>Jakie masz skladniki?</h1>
<form action="{% url 'search_results' %}" method="get">
<input name="q" type="text" placeholder="Search...">
</form>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
views:
from django.shortcuts import render
from django.db.models import Q #new
from .models import Recipe
from .models import Ingredient
from django.contrib import messages
from django.shortcuts import redirect
def drink_list(request):
template = "drinks/drink_list.html"
return render(request, template)
def search_results(besos):
query = besos.GET.get('q')
if not query or query == ' ' or query == ' ' or query == ' ':
#how to write this ^ in shortest way? if string is empty then return 'drink_list'
messages.error(besos, "Search field can not be empty")
return redirect('drink_list')
else:
q = Q()
for queries in query.split():
q |= (Q(ingredients__ingredient_name__icontains=queries))
#why it look for 'sok z cytryny' and show as well sok z limonki
results = Recipe.objects.filter(q)
template = "drinks/search_results.html"
context = {
'results' : results,
}
return render(besos, template, context)
URL:
urlpatterns = [
path('', views.drink_list, name='drink_list'),
path('search/', views.search_results, name='search_results'),
path('no_name/', views.drink_list, name='drink_list'),
]
What about trying this with some javascript? You can blank out the input tag on pageload.
<script>
window.onload = function(){
document.getElementByName("q").value = "";
}
</script>
Or you can try this
<script>
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
document.getElementByName("q").value = "";
}
</script>
Try this
<button onclick="history.back()">Go Back</button>
Clicking Go Back.get previous sections without clear inputs..
Related
I'm trying to clone the Instagram web page using Django(version-3.1).
My Django project has an app called 'post'.
One of its template I have a form which is posting a comment to a post. The form post request should call the path('add_comment/',views.add_comment,name='add_comment'), but It's calling path('<slug:slug>/',views.post_details,name='post_details'), instead. And raising DoesNotExist at /post/add_comment error. I added print() statement at the beginning of both add_comment() and post_details() methods to find out which is running when the request is made. I have no idea what I have done wrong.
The project GitHub link - https://github.com/mirasel/Instagram_Clone
the post_details.html template is -
{% extends 'base.html' %}
{% load static %}
{% block title %} post {% endblock %}
{% block profilephoto %} {{ propic.url }} {% endblock %}
{% block body %}
<div>
<div>
<img src="{{post.image.url}}" alt="post" height="250px" width="250px">
</div>
<div>
<a href="{% url 'instagram:profile' post.uploader %}">
<img src="{{uploader.profile_pic.url}}" alt="{{uploader}}" style="border-radius: 50%;" height="24px" width="24px">
{{ post.uploader }}
</a><br>
<p>{{ post.date_published.date }}</p>
</div>
<div>
<p>{{ post.caption }}</p>
</div>
<div>
<form action="{% url 'post:add_comment' %}" id="comment_form" method="POST">
{% csrf_token %}
<textarea name="comment" id="comment" cols="30" rows="1" placeholder="Write a comment..."></textarea>
<input type="hidden" name="slug" id="slug" value="{{post.slug}}">
<!-- <input type="submit" style="display: none;" name="submit"> -->
</form>
<script>
$(function(){
$("#comment").keypress(function (e) {
if(e.which == 13 && !e.shiftKey) {
$(this).closest("form").submit();
e.preventDefault();
}
});
});
</script>
{% endblock %}
the views.py -
from django.shortcuts import render,redirect
from instagram.views import get_nav_propic,get_profile_details
from .models import UserPost,PostComment,PostLike
from django.http import JsonResponse
def get_post_likes(post):
likes = PostLike.objects.filter(post=post)
total_likes = len(likes)
likers = []
for l in likes:
likers.append(get_profile_details(l.liker))
return {'likers':likers,'total_likes':total_likes}
def get_post_comments(post):
comments = PostComment.objects.filter(post=post)
total_comments = len(comments)
commenter = []
comment = []
for c in comments:
commenter.append(get_profile_details(c.commenter))
comment.append(c.comment)
postcomment = zip(commenter,comment)
return {'post_comment':postcomment,'total_comments':total_comments}
def upload_post(request):
if request.method == 'POST':
image = request.FILES['post_img']
caption = request.POST['caption']
uploader = request.user
UserPost.objects.create(uploader=uploader,image=image,caption=caption)
return redirect('instagram:feed')
else:
context = {
'propic' : get_nav_propic(request.user)
}
return render(request,'post/upload_post.html',context)
def post_details(request,slug):
print('I am here in post details')
post = UserPost.objects.get(slug=slug)
context = {
'propic' : get_nav_propic(request.user),
'post' : post,
'uploader' : get_profile_details(post.uploader),
'LIKES' : get_post_likes(post),
'COMMENTS' : get_post_comments(post),
}
return render(request,'post/post_details.html',context)
def add_comment(request):
print('I am here in add comment')
if request.method == 'POST':
post_slug = request.POST.get('slug')
post = UserPost.objects.get(slug=post_slug)
user = request.user
comment = request.POST.get('comment')
PostComment.objects.create(post=post,commenter=user,comment=comment)
return redirect('post:post_details',slug=post_slug)
the urls.py -
from django.urls import path
from . import views
app_name='post'
urlpatterns = [
path('upload_post/',views.upload_post,name='upload_post'),
path('<slug:slug>/',views.post_details,name='post_details'),
path('add_comment/',views.add_comment,name='add_comment'),
]
The error - Error page
Solved
I had to make the URL path of add_comment as following-
#previous one
path('add_comment/',views.add_comment,name='add_comment'),
#modified one
path('comment/add_comment/',views.add_comment,name='add_comment'),
This is because the pattern for the slug URL and add comment URL were similar.
Because Django will process the urlpatterns sequentially, from docs:
Django runs through each URL pattern, in order, and stops at the first
one that matches the requested URL, matching against path_info.
And '/add_comment' is a valid slug <slug:slug>, so post_details will be called.
So you should keep the definition of the most generic url patterns at last:
urlpatterns = [
path('upload_post/',views.upload_post,name='upload_post'),
path('add_comment/',views.add_comment,name='add_comment'),
path('<slug:slug>/',views.post_details,name='post_details'),
]
Hopefully this will work for you.
I'm new to Django.
Trying to build an app that adds two names. Pretty Basic.
Built a page that collects the names but not printing the final result.
Here is my code:
urls.py - inside the app
urlpatterns = [
path('',views.home, name='home'),
path('add',views.addname,name='add')
]
views.py
from django.shortcuts import render
from django.http import HttpResponse
def home(request):
return render(request,'input.html')
def addname(request):
val1 = (request.POST['fname'])
val2 = (request.POST['lname'])
res = 'Hi' + val1 +val2
return render(request, 'resultprint.html',{'resultprint':res})
templates/input.html
{% block content %}
<h1>Hello!</h1>
<form action='addname' method='post'>
{% csrf_token %}
Enter 1st name : <input type='text' name='fname'><br>
Enter 2nd name : <input type='text' name='lname'><br>
<input type='submit'>
</form>
{%endblock%}
templates/resultprint.html
{% block content %}
Result: {{resultprint}}
{%endblock%}
Below are the screenshots:
Couldn't really find where is the mistake happening.
I added the templates and app in the Settings file.
You have to set the same url in your urls.py :
urlpatterns = [
path('', views.home, name='home'),
path('addname', views.addname, name='addname')
]
But you can use directly the name of the url in your html file like that :
{% block content %}
<h1>Hello!</h1>
<form action='{% url 'addname' %}' method='post'>
{% csrf_token %}
Enter 1st name : <input type='text' name='fname'><br>
Enter 2nd name : <input type='text' name='lname'><br>
<input type='submit'>
</form>
{%endblock%}
This is my first project with Django and I got a problem. In the backend I created news, but I have an issue displaying the news on the frontpage. Models should be fine since I can create news into the admin panel. But I can't figure out where is my mistake.
I have app 'pages'>views.py
from django.shortcuts import render, redirect, get_object_or_404
from mainnews.models import Mainnews
# Create your views here.
def home_view(request):
main = Mainnews.objects.all()
context = {
'main' : main
}
return render(request, 'index.html', context)
root>urls.py
from pages.views import home_view
urlpatterns = [
path('admin/', admin.site.urls),
path('', home_view, name = 'home'),
]
and app mainnews>views.py
from django.shortcuts import render, get_object_or_404
from .models import Mainnews
# Create your views here.
def index(request):
main = Mainnews.objects.all()
context = {
'main' : main
}
return render(request, 'index.html', context)
and the template mainnewsandevents.html that extends to index
{% block content %}
<!-- Section 2 News and Events -->
<div id="news-container">
<div class="jumbo-news">
<img id = 'jumboImgUrl' class='jumbo-img' src="{{ main.image.url }}">
<h2 id = 'jumboTitle' class='jumbo-title'>{{ main.title }}</h2>
<h4 id = 'jumboDescription' class='jumbo-parag'>{{ main.description }}</h4>
</div>
{% endblock %}
Fix it like this:
def home_view(request):
main = Mainnews.objects.first()
# or main = Mainnews.objects.last()
# other code
or if you need to show all objects on your template use something like it:
{% block content %}
<!-- Section 2 News and Events -->
<div id="news-container">
<div class="jumbo-news">
{% for article in main %}
<img id = 'jumboImgUrl' class='jumbo-img' src="{{ main.image.url }}">
<h2 id = 'jumboTitle' class='jumbo-title'>{{ main.title }}</h2>
<h4 id = 'jumboDescription' class='jumbo-parag'>{{ main.description }}</h4>
{% endfor %}
</div>
{% endblock %}
Depends on your needs.
Also you shouldn't use not obvious names for variables so you shall use main_news instead of main.
main is an array of objects right so you need a for loop to get every object
{% block content %}
<!-- Section 2 News and Events -->
<div id="news-container">
<div class="jumbo-news">
{% for obj in main %}
<img id = 'jumboImgUrl' class='jumbo-img' src={{ obj.image.url }}>
<h2 id = 'jumboTitle' class='jumbo-title'>{{ obj.title }}</h2>
<h4 id = 'jumboDescription' class='jumbo-parag'>{{ obj.description }}</h4>
{% endfor %}
</div>
{% endblock %}
Any help would be greatly appreciated
index.html
{% extends 'base.html' %}
{% block content %}
<div>
<h1>Welcome Home</h1>
<form action="{% url 'calc:home' %}" method="GET">
<!-- {% csrf_token %} -->
Enter 1st Number : <input type="text" name="num1"><br><br>
Enter 2nd Number : <input type="text" name="num2"><br>
<input type="submit" name="" value="Add"><br><br>
</form>
Result of the game is : {{result}}
</div>
{% endblock %}
views.py
from django.shortcuts import render
from django.http import HttpResponse
def home_view(request):
if request.GET.get('num1'):
val1 = int(request.GET.get("num1"))
val2 = int(request.GET.get("num2"))
res = val1 + val2
return render(request, 'calc/index.html',{'result':res})
urls.py
from django.urls import path
from . import views
app_name = 'calc'
urlpatterns = [
path('', views.home_view, name='home'),
]
i get this error when running the server: UnboundLocalError: local variable 'res' referenced before assignment
I hope this will help. Basically you are using a variable outside of it's scope. you defined res in "if" block but called outside "if" though it was not present in that scope.So you should first assign a default value.
def home_view(request):
res=0
if request.GET.get('num1'):
val1 = int(request.GET.get("num1"))
val2 = int(request.GET.get("num2"))
res = val1 + val2
return render(request, 'calc/index.html',{'result':res})
I am creating an app when a user can search for recipes by inputing some ingredients in search-field.
I would like to do that when search-field is empty or string is empty a user get error.message 'Please put input.' But after i have implemented message.error into views and template it only returns the same page without this informaton 'Please put input.'. Do you know what i made wrong here?
My views:
from django.shortcuts import render
from django.db.models import Q #new
from .models import Recipe
from .models import Ingredient
from django.contrib import messages
from django.shortcuts import redirect
def drink_list(request):
template = "drinks/drink_list.html"
return render(request, template)
def search_results(besos):
query = besos.GET.get('q')
if not query or query == ' ' or query == ' ' or query == ' ':
messages.error(besos, "Please put input")
return redirect('drink_list')
else:
q = Q()
for queries in query.split():
q |= (Q(ingredients__ingredient_name__icontains=queries))
#why it look for 'sok z cytryny' and show as well sok z limonki
results = Recipe.objects.filter(q)
template = "drinks/search_results.html"
context = {
'results' : results,
}
return render(besos, template, context)
My template search_results:
{% if results %}
{% for drink in results %}
<div>
<p>{{ drink.recipe_name }}</p>
<p>Preparation: {{ drink.preparation }}</p>
<p>Ingredients:
{% for ingredient in drink.ingredients.all %}
{{ingredient.ingredient_name}}{% if not forloop.last %},{% endif %}
{% endfor %}
</p>
</div>
{% endfor %}
{% elif messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% else %}
<div>Such ingredients do not exist</div>
{% endif %}
If there is no query term , you are currently redirecting to:
return redirect('drink_list')
but you are not passing the message on to the drink_list view.
In case of redirect, you can pass the message string as argument
return redirect('{}?message=Please put input'.format(reverse('drink_list)))
Then your drink_list template must include:
<ul class="messages">
<li>{{ message }}</li>
</ul>
You need to further modify your drink_list function to get the message argument:
def drink_list(request):
template = "drinks/drink_list.html"
message = request.GET.get('message', ''))
return render(request, template, message=message)
And finally your url must include the optional message argument :
path('drink_list/', views.drink_list,name='drink_list'),