Django query works in shell, but jinja wont recognize in template - python

Right now I can run a query in the python shell and have it return True, but when trying to replicate in my html jinja template, I can't get it return the same True result.
I have a query that puts a Post.object.get(id=1) as a variable.
P1=Post.objects.get(id=1)
then ran:
P1.liked_by.all()
which does return results:
<QuerySet [<User: User object(10)>, <User: User object (12), <User: User
object (13)>]>
then I put a variable in for a User found in that query:
JV= User.objects.get(id=10)
This user id is found in the P1.liked_by.all() query, so now when I test to see if it is found.
JV in P1.liked_by.all()
True
Now when I try to access this in my html jinja template. I can not get it to check against it and return true. Even though I can print the values on the page.
Here is my Views.py:
def topic(request,topic_id):
if not 'u_id' in request.session:
return redirect('/')
print(request.session)
context={
"topic":Topic.objects.get(id=topic_id),
"user":User.objects.get(id=request.session["u_id"]),
"posts":Post.objects.filter(topic=topic_id),
}
return render(request, 'topic.html', context)
Here is my HTML:
{% for post in posts %}
<div class="cast-content">
<h3>Casting submit by <u>{{post.user.user_name}}!</u></h3>
<p>number of likes:{{post.liked_by.count}}</p>
<p>post id:{{post.id}}</p>
<p>user_id in session= {{user.id}}</p>
<p>liked by:{{post.liked_by.all}}</p>
<img src="{{post.image.url}}" class="post-pix" alt="...">
<br>
<p>post liked_by values: {{post.liked_by.values}}</p>
{% if user.id in post.liked_by.all %}
Un-Like
{% else %}
<form action="/add-like" method="post">
{% csrf_token %}
<input type="hidden" name="post_id" value="{{post.id}}">
<input type="hidden" name="topic" value="{{topic.id}}">
<input type="submit" value="Like">
</form>
{% endif %}
{% if user.id == post.user.id %}
Remove
{% endif %}
</div>
{% endfor %}
I can not figure out why I can print the values in the template but when I run the {% if %} statement to check if it exists in the table It can't find it therefore defaulting into the {% else %} statement every single time. Any help at all is so greatly appreciated!

Related

Failed to get value from html page in Django

I have a problem with trying to get a response from my HTML page using Django (admin).
I have a pretty simple div = contenteditable and need to pass data from this div back after the submit button was clicked.
Everything, including choosing selection and opening the intermediate page works fine. But when I tapped submit button, the condition if "apply" in request.POST failed to work.
Please, tell me, what I'm doing wrong?
This is my Django admin:
class QuestionAdmin(AnnotatesDisplayAdminMixin, admin.ModelAdmin):
def matched_skills(self, question):
return ', '.join(s.name for s in question.skills.all())
def update_skills(self, request, queryset):
if 'apply' in request.POST:
print("something")
skills = []
for question in queryset:
skills.append(self.matched_skills(question))
return render(request,
'admin/order_intermediate.html',
context={'skills': skills})
update_skills.short_description = "Update skills"
This is my order_intermediate.html page:
{% extends "admin/base_site.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<h1>Adjust skills. </h1>
{% for skill in skills %}
<div>
<div id="title" style="margin-left: 5px" contenteditable="true" > {{ skill }} </div>
</div>
{% endfor %}
<input type="hidden" name="action" value="update_status" />
<input type="submit" name="apply" value="Update skills"/>
</form>
{% endblock %}
Actually, request.POST is an HttpRequest object. For getting available keys in the body of the request, you need to use "request.POST.keys()" method. So, you can simply change your condition to:
if 'apply' in request.POST.keys():
print("something")
In my knowledge, you can not send div content with form submit. However you can use input tag with array in name attribute for this. This will send an array as post variable when submit
First, send skills as a enumerate object from your views
return render(request, 'admin/order_intermediate.html', context={'skills': enumerate(skills)})
Then edit your html to this (Note: if you have css in title id, change it to title class)
{% for i,skill in skills %}
<div>
<input class="title" name="skill[{{ i }}]" value="{{ skill }}" style="margin-left: 5px">
</div>
{% endfor %}
and handle array with any action you want to perform in update_skills()
for skill in request.POST.getlist('skill[]'):
# your code

How do you iterate through two items in a model and display on site using Django?

I have a models.py with the following fields:
class ChatStream(models.Model):
bot = models.TextField()
user = models.TextField()
name = models.CharField(max_length=100, null=True)
created_date = models.DateTimeField(auto_now_add=True)
And I'd like on a website to iterate through "bot" and "user" one at a time, so the site would hypothetically display something like:
bot: hello!
user: what's up?
bot: I'm good
user: What's your name
bot: bot is my name
.... etc. this would keep going...
So in my views.py I have
def displayDict(request):
m = ChatStream.objects.all()
return render(request, 'chatStream.html',
{"chat": m})
def send(request):
message = request.POST.get('userMessage', False)
ip = visitor_ip_address(request)
response = routes(message, ip)
print(ip, "user sent:", message, "bot response:", response)
chatItem = ChatStream(bot=response, user=message, name=ip)
chatItem.save()
return HttpResponseRedirect('/chat/')
Then in my template, chat.html I have
{% block chatStream %} {% endblock %}
And chatStream.html (this is where the error is happening I believe... how do you iterate through two items in the model so they appear one after the other on the html file?)
{% extends 'chat.html' %}
{% block chatStream %}
{% for a in bot%}
{% for b in user%}
<p>
<b>bot:</b> {{a}} <br>
<b>user:</b> {{b}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}
But this does not work -- no text from the model is displayed on the site. I am not understanding how to iterate through two items within the model at once inside of the chatStream.html.
A lot going on here, lets try to break it down:
First, you need to pass context variables to your templates if you want to render them using the (jinja-like) Django template rendering system.
Your view function for rendering the template would look like this:
views.py
def render_chat_page(request):
# do some logic:
...
# pack the context variables:
context = {
'some_key' : 'some_value',
'chat_streams' : ChatStream.objects.all(),
...
}
return render(request, 'chat_page.html', context=context)
Ok, now that we've passed the context variables to the template, we can render html elements using the variables like so:
template.html
<div> The value of "some_key" is: {{some_key}} </div>
{% for chat_stream in chat_streams %}
<div> user says: {{chat_stream.user}}</div>
<div> bot says: {{chat_stream.bot}}</div>
{% endfor %}
This will render the user and bot messages for each ChatStream object. However my hunch is that this is not entirely what you're after, instead you may want something more dynamic.
In your displayDict view you're passing a QuerySet to the context. So, you need to loop over the QuerySet in your template.
{% extends 'chat.html' %}
{% block chatStream %}
{% for item in chat %}
<p>
<b>bot:</b> {{item.bot}} <br>
<b>user:</b> {{item.user}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}

Why won't my view load in properly? (Django)

I am extremely new to Django's framework and recently finished the introductory series on their website, and I have tried adding a new view in which I use a form to create an object.
The problem is, whenever I access the view, it immediately executes the HttpResponseRedirect(), and second of all it does not even return a response.
views.py
def create(request):
context = {
'questionfields': Question.__dict__,
}
submitbutton = request.POST.get('Create', False)
if submitbutton:
new_question = Question(question_text=request.POST.get('question_text', ''), pub_date=timezone.now())
if new_question.question_text == '':
context = {
'questionfields': Question.__dict__,
'error_message': "No poll question entered."
}
del new_question
return render(request, 'polls/create.html', context)
else:
return HttpResponseRedirect(reverse('create'))
create.html
{% extends "polls/base.html" %}
{% block title %}Create a Poll{% endblock title %}
{% block header %}Create:{% endblock header %}
{% load custom_tags %}
{% block content %}
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:create' %}" method="post"> {% csrf_token %}
{% for field in questionfields %}
{% if field == 'question_text' %}
<label for="{{ field }}">{{ field|capfirst|replace }}:</label>
<input type="text" name="{{ field }}" id="{{ field }}">
<br>
{% else %}
{% endif %}
{% endfor %}
<br>
<input type="submit" value="Create" name="submit">
</form>
{% endblock content %}
I attempted to make it so if I enter text into the question_text input, when I click the submit button it creates a Question object with question_text being the entered text and the pub_date being the present time.
However, it merely gives a failed redirect.
I don't fully understand how the render() function works in a view and how its positioning in the logic affects the rendering of the view, so please excuse any of my mistakes.
I would like to know why it does not carry out any of the code from submitbutton... to else: , and how to fix this to get the view to work as intended. If anyone could help with my rendering and view problem it would be great.
Error image
You're using recursive here
return HttpResponseRedirect(reverse('create'))
In case it fails, it will redirect to this Create function again, and fail, and redirect again, again....
Try to do it like this:
def create(request):
context = {
'questionfields': Question.__dict__,
}
submitbutton = request.POST.get('Create', False)
if submitbutton:
new_question = Question(question_text=request.POST.get('question_text', ''), pub_date=timezone.now())
if new_question.question_text == '':
context = {
'questionfields': Question.__dict__,
'error_message': "No poll question entered."
}
del new_question
# Just render the page here with the initial context
return render(request, 'polls/create.html', context)

dynamic pagination with django

Okay so this is first time using pagination with Django and I am trying to prevent it from reloading my view on each page turn.
I'm handling the pagination in the view like this:
page = request.GET.get('page', 1)
print page
paginator = Paginator(list(od.iteritems())[:24], 12)
try:
data = paginator.page(page)
except PageNotAnInteger:
data = paginator.page(1)
except EmptyPage:
data = paginator.page(paginator.num_pages)
print data
save_query_form = SaveQueryForm(request.POST or None)
#if request.method == 'POST':
if save_query_form.is_valid():
profile = save_query_form.save(commit=False)
profile.user = request.user
profile.save()
context = {
"title":"Search",
'data': data,#list(od.iteritems()),
'tools': od_tools.iteritems(),
'methods': od_methods.iteritems(),
'data4': od_data.iteritems(),
'search_phrase': " ".join(instanceValuesString),
'json_dump': js_data,
'form': save_query_form,
}
return render(request, 'results.html', context)
and the pagination is handled in the html:
{% if data.has_other_pages %}
<div id='page-slide'>
<ul class="pagination" start='$offset'>
{% if data.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in data.paginator.page_range %}
{% if data.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if data.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
</div>
{% endif %}
The issue that I am having is that whenever I switch to another page my entire view will run again and the data will does not reflect the original search query and instead defaults to an empty query.
I was wondering if there is a simple way to either handle pagination dynamically or prevent the page reload when toggling between pages?
Any help is appreciated, thanks.
Update Search Form:
<form action="{% url 'results-view' %}" method="POST" class="autocomplete-me ui-widget" id="myform" >
{% csrf_token %}
<div class="ui-widget" style="text-align:center;">
<input type="text" id="id_q" name="q" placeholder="{{ search_phrase }}">
<br></br>
<div style="text-align:center;" id='adjust-button'>
<input type='submit' class='btn btn-secondary btn-lg' id ='search-btn' value='Search'/>
<a class='btn btn-secondary btn-lg' id ='clear-btn' href="{% url 'inital' %}">Clear</a>
</div>
</div>
</form>
You noted in a comment that you get your search value with instanceValuesString = request.POST.get(u"q").encode('utf-8').strip(). As one commenter correctly pointed out, this means that when you click your "next page" links (making a GET request), your view doesn't receive the information it needs to return search results.
One way to fix this would be to get your instanceValuesString from a GET request instead of a POST request. For instance, perhaps your list view is at
http://example.com/StuffList
You could look for URLs that provide a search querystring:
http://example.com/StuffList?search=goodstuff
And then grab that in your view:
instanceValuesString = request.GET.get('search', None)
if instanceValuesString is not None:
#you have detected a search query; filter results, process request, etc.
One side effect here is that the way you currently construct your next/previous page URLs will break. Consider the example search URL; your current template would construct a link for page 2 like so:
http://example.com/StuffList?search=goodstuff?page=2
This won't work; it should be &page=2. Fortunately there's an easy fix; check out the second answer to this question: Altering one query parameter in a url (Django). Using that url_replace instead of constructing those links with the basic url template tag will solve this part of the issue.
This is very much simplified with below package
http://django-simple-pagination.readthedocs.io/en/latest/

Django CRUD doesn't reloads the model

When I do a crud action to my database it won't change on the website after refreshing the page. I have to restart the server "python manage.py runserver" everytime to see the changes on my website.
I asked another student about this problem and he said he didn't had the problem. I tried to find it on the internet but with no success.
It's add the richting but doesn't show it until I do python manage.py runserver.
richtingen.html (where I add a richting and show the richting)
{% extends 'main_app/base.html' %}
{% load staticfiles %}
{% block main %}
<main>
<div class="messages">
<h2>Richtingen</h2>
<h3>Nieuwe richting maken:</h3>
<form class="all_forms" action="post_richting/" method="POST">
{% csrf_token %}
{{ form.as_p }}
<div>
<button type="submit" name="submit">Verzenden</button>
</div>
</form>
<hr>
<div class="messages">
{% for richting in richtingen %}
<h3 id="{{richting.id}}">{{richting.naam}}</h3>
<p>{{richting.omschrijving}}</p>
Wijzigen
Verwijderen
<hr>
{% endfor %}
</div>
</div>
</main>
{% endblock %}
urls.py
url(r'^[rR]ichtingen/$', views.richtingen, name='richtingen'),
url(r'^richtingen/post_richting/$', views.post_richting, name='post_richting'),
views.py
titel = 'KA Go Malle'
volledigeTitel = 'Koninklijk Atheneum Go Malle'
richtingenObjects = Richtingen.objects.all()
def richtingen(request):
form = RichtingForm()
context = {'titel': titel,
'volledigeTitel': volledigeTitel,
'form': form,
'richtingen': richtingenObjects}
return render(request, 'main_app/richtingen.html', context)
def post_richting(request):
form = RichtingForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit = True)
return HttpResponseRedirect('/richtingen')
You have defined the relevant data outside a function. I'm not sure why you have done this, but that means the query only evaluated once: when the module is first loaded. Don't do this; define the variables inside the function that uses them, so that the query is made ever time.

Categories

Resources