#Flask Code
from flask import Flask, render_template
app = Flask(__name__)
posts = [
{
'author': 'User',
'title': 'Test',
'content': 'First post',
'date_posted': '2021, 4 ,13',
},
{
'author': 'User2',
'title': 'Flask is cool',
'content': 'Flask testing',
'date_posted': '2021, 4 ,14'
}
]
#app.route('/')
#app.route('/home')
def hello():
return render_template('home.html', posts=posts)
#ignore this
#app.route('/about')
def about():
return render_template('about.html')
if __name__ == '__main__':
app.run(debug=True)
#HTML Code
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
{% for post in posts %}
<p>By {{ posts.author }} on {{ posts.date_posted }}</p>
<p>By {{ post.content }}</p>
{% endfor %}
</body>
</html>
the for loop is executing but the values in the dict. are not displaying, I am very new in flask
so I'm pretty sure I have to add in some extra code..? Any help is appreciated :D
Use your loop variable post inside your for loop instead of posts.
{% for post in posts %}
<p>By {{ post.author }} on {{ post.date_posted }}</p>
<p>By {{ post.content }}</p>
{% endfor %}
Related
I am trying to display 2 forms in my contact.html page in a Django project. Each form needs to display a success message when being successfully submitted by users. The problem is that both forms in the page show the same success message when either of them being submitted.
How can I tie the success message to the submitted form on my HTML page?
forms.py
from dataclasses import field, fields
from logging import PlaceHolder
from socket import fromshare
from django import forms
from .models import ServiceRequest, Contact, Newsletter
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['name','email','phone','message']
class NewsletterForm(forms.ModelForm):
class Meta:
model = Newsletter
fields = ['name','email']
views.py
from http.client import HTTPResponse
from multiprocessing import context
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import ContactForm, NewsletterForm, ServiceRequest, ServiceRequestForm
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.urls import reverse
def Contact(request):
contact_form = ContactForm(request.POST or None)
newsletter_form = NewsletterForm(request.POST or None)
if request.method == 'POST' and contact_form.is_valid():
contact_form.save()
messages.success(request, "Thanks for contacting us!")
return HttpResponseRedirect(request.path_info)
elif request.method == 'POST' and newsletter_form.is_valid():
newsletter_form.save()
messages.success(request, "Thanks for joining our newsletter!")
return HttpResponseRedirect(request.path_info)
context = {
"contact_form":contact_form,
"newsletter_form":newsletter_form,
}
return render(request, "main/contact.html", context)
contact.html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<div>
<!-- Message from backend -->
{% for message in messages %}
{% if message.tags == 'success' %}
<div>{{message}}
</div>
{% endif %}
{% endfor %}
<form method="POST">
{% csrf_token %}
<div class="row">
{{ contact_form.name|as_crispy_field }}
{{ contact_form.email|as_crispy_field }}
{{ contact_form.phone|as_crispy_field }}
{{ contact_form.message|as_crispy_field }}
</div>
</div>
<button type="submit">Submit</button>
</form>
</div>
<div>
<!-- Message from backend -->
{% for message in messages %}
{% if message.tags == 'success' %}
<div>{{message}}
</div>
{% endif %}
{% endfor %}
<form method="POST">
{% csrf_token %}
<div class="row">
{{ newsletter_form.name|as_crispy_field }}
{{ newsletter_form.email|as_crispy_field }}
</div>
<button type="submit">Submit</button>
</form>
</div>
{% endblock %}
After submitting one form on this page, both forms show the success message:
You can use extra_tags of messages framework Django docs:
So in view:
messages.success(request, "Thanks for contacting us!", extra_tags='form1')
And in template:
{% for message in messages %}
{% if message.tags == 'success' and message.extra_tags == 'form1' %}
<div>{{message}}
</div>
{% endif %}
{% endfor %}
I am trying to get data from a JSON, which was fetched from an API I created to display on my Django Template.
The API is just a simple API which store a post hit counts and its id, the json is formatted as below:
[
{
"object_pk": 3,
"hits": 15
},
{
"object_pk": 1,
"hits": 21
}
]
Here is my views.py file:
class BlogListView(ListView):
model = Post
template_name = "home.html"
class BlogDetailView(HitCountDetailView, DetailView):
model = Post
template_name = "post_detail.html"
count_hit = True
data = {
"hits": get_cloudapi_data(),
}
class ResumePageView(TemplateView):
template_name = "resume.html"
And my service.py file, which have the get_cloudapi_data() function:
def get_cloudapi_data():
url = "my-api-address"
r = requests.get(url)
hitcount = r.json()
return hitcount
Below is my HTML template, post_detail.html used for displaying this data:
{% extends "base.html" %}
{% load hitcount_tags %}
{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p> {% get_hit_count for post %} views</p>
<p> {{ post.body }}</p>
{% for hit in hits %}
<p>{{ hit.object_pk }}</p>
<p>{{ hit.hits }}</p>
{% endfor %}
</div>
{% endblock content %}
It only shows the title, body and the hit count retrieve with the hitcount app not my API data
I have printed out the hitcount and the data if it would help
hitcount
[{'object_pk': 3, 'hits': 15}, {'object_pk': 1, 'hits': 21}]
data
{'hits': [{'object_pk': 3, 'hits': 15}, {'object_pk': 1, 'hits': 21}]}
I am new to working with an API with Django, so I am unsure where I went wrong.
im trying to add to my html a button that appears only on certain events, that works for me but i want to add a onclick script/function that will invoke a backend view.py function that deletes the specific room on click, the room model is : owner(fk), name, slug.
and the user model is : username password1 password2.
i just need to know how to invoke an onclick event that will call the backend function in my views.
rooms.html
{% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<button class="room-delete" id="roomDelete">Delete Room</button>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
views.py
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
from django.contrib import messages
from .models import Room, Message
#login_required
def rooms(request):
if request.method == 'POST':
room_owner = request.user
room_name = request.POST['room-name']
if not Room.objects.filter(slug = room_name).exists():
if room_name == '' or room_name.isspace() or room_name.startswith(' '):
messages.info(request, 'Invalid room name, spaces-only or string that starts with spaces is invalid.')
else:
new_room = Room(owner = room_owner,name = room_name,slug = room_name)
new_room.save()
else:
messages.info(request, 'That room already exists!, try a different name.')
rooms = Room.objects.all()
return render(request, 'room/rooms.html', {'rooms': rooms})
#login_required
def room(request, slug):
room = Room.objects.get(slug=slug)
messages = Message.objects.filter(room=room)[0:25]
return render(request, 'room/room.html', {'room': room, 'messages': messages})
#csrf_exempt
def delete_room(request): ## <<------ invoke this from html call.
print("hey")
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('', views.delete_room, name='delete_room'),
]
now i have more 2 urls.py, the project has 3 folders, 1 main (livechatapp) with settings and all, one for core htmls (core) and one for rooms html (room)
core/urls
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
path('', views.frontpage, name='frontpage'),
path('signup/', views.signup, name='signup'),
path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
and finally
livechatapp/urls
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('core.urls')),
path('rooms/', include('room.urls')),
path('admin/', admin.site.urls),
]
and this is the projects overview folders and files :
this is the project
IF you want do it in standard html:
% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<form method="POST" action="{% url 'delete_room' room.slug %}>
<button type="submit" class="room-delete">Delete Room</button></form>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
urls:
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('delete/<slug:slug>/', views.delete_room, name='delete_room'),
]
views:
#csrf_exempt
def delete_room(request,slug):
if request.method == 'POST':
try:
room = Room.objects.get(slug=slug, owner=request.user)
room.delete()
except ObjectDoesNotExist:
print('there is no room with this slug or you are not owner')
return redirect('rooms')
i advice to use csrf. allways try to use POST when manipulatind data in db.
If you want to work it without redirect you need to think of ajax call or maby htmx
I am testing the api from block.io https://block.io/api/simple/python
{
"status" : "success",
"data" : {
"network" : "BTCTEST",
"available_balance" : "0.0",
"pending_received_balance" : "0.0",
"balances" : [
{
"user_id" : 0,
"label" : "default",
"address" : "2NCjjB8iVKu9jnYpNcYKxxRYP9w6eWXZAq4",
"available_balance" : "0.00000000",
"pending_received_balance" : "0.00000000"
}
]
}
}
I would like to display for example only the wallet address of the user in question so that he can make a deposit.
My views.py
from django.shortcuts import render
from block_io import BlockIo
version = 2 # API version
block_io = BlockIo('28a8-ba34-8b81-137d', '1111111', version)
def index(request):
balance = block_io.get_address_balance(labels='shibe1')
context = {'balance': balance}
return render(request, 'home.html', context)
home.html
<h1>Block.io API</h1>
{{ balance }}
<h1>I want display example this data</h1>
<h1>Label: default</h1>
<h1>Available balance: 0.00000000</h1>
<h1>Pending received balance: 0.00000000</h1>
<h1>Address: 2NCjjB8iVKu9jnYpNcYKxxRYP9w6eWXZAq4</h1>
When I do this all the data is displayed but example I only want to address
Image displayed data
{'status': 'success', 'data': {'network': 'BTCTEST', 'available_balance': '0.0', 'pending_received_balance': '0.0', 'balances': [{'user_id': 1, 'label': 'shibe1', 'address': '2NADUMWksxJZRKPSNXya8R2LYQY2fGa5mNY', 'available_balance': '0.00000000', 'pending_received_balance': '0.00000000'}]}}
How can I refer only to the data that I want?
You can perform all sorts of lookups on variables in Django Template language using just the . operator. Also your data has a list so you would need to loop over it:
<h1>Block.io API</h1>
<h1>I want display example this data</h1>
{% for bal in balance.data.balances %}
<h1>Label: {{ bal.label }}</h1>
<h1>Available balance: {{ bal.available_balance }}</h1>
<h1>Pending received balance: {{ bal.pending_received_balance }}</h1>
<h1>Address: {{ bal.address }}</h1>
{% endfor %}
Please refer to below file changes :
My views.py
from django.shortcuts import render
from block_io import BlockIo
version = 2 # API version
block_io = BlockIo('28a8-ba34-8b81-137d', '1111111', version)
def index(request):
balance = block_io.get_address_balance(labels='shibe1')
context = {'all_balance': balance['data']['balances']}
return render(request, 'home.html', context)
home.html
<h1>Block.io API</h1>
{% for balance in all_balance %}
<h1>Label: {{ balance.label }}</h1>
<h1>Available balance: {{ balance.available_balance }}</h1>
<h1>Pending received balance: {{ balance.pending_received_balance }}</h1>
<h1>Address: {{ balance.address }}</h1>
{% endfor %}
The Goal
I'm creating a Flask website to serve as the UI for a custom bioinformatics pipeline. The way I'm trying to design it is such that the user fills in the pipeline parameters (e.g. Project Name, Data Type, Number of Samples, etc.) in a multi-page form (kind of like the checkout process in online ordering) and then I would like these parameters to be saved to the user's account page as separate "posts".
The Issue
I've been following a Flask Tutorial online (https://www.youtube.com/watch?v=QnDWIZuWYW0&list=PL-osiE80TeTs4UjLw5MM6OjgkjFeUxCYH&index=2) about how to save the "posts" (pipeline parameters) to the user's dashboard by supplying fake or sample "posts" to the dashboard's html template, but nothing shows up at all. What am I doing wrong?
The Source Code
routes.py:
posts = [
{
'username': 'claudiadast',
'date_posted': 'September 22, 2018',
'stack_name': 'wgs-test-stack',
'start_point': 'fastq',
'input_uri': 's3://pipeline-validation/smallfq/',
'build': 'GRCh38',
'ome': 'wgs',
'project_id': 'summerwater598'
},
{
'username': 'claudiadast',
'date_posted': 'September 10, 2018',
'stack_name': 'clinical-exome',
'start_point': 'fastq',
'input_uri': 's3://pipeline-validation/Clinex/',
'build': 'GRCh38',
'ome': 'wes',
'project_id': 'summerwater598'
}
]
#app.route('/')
#app.route('/home')
def home():
return render_template('home.html', posts=posts)
home.html:
{% extends "layout.html" %}
{% block content %}
{% for post in posts %}
<h1>{{ post.stack_name }}</h1>
<p>{{ post.username }} on {{ post.date_posted }}</p>
<p>Pipeline Parameters:</p>
<p>{{ post.stack_name }}</p>
<p>{{ post.start_point }}</p>
<p>{{ post.input_uri }}</p>
<p>{{ post.build }}</p>
<p>{{ post.ome }}</p>
<p>{{ post.project_id }}</p>
{% endfor %}
{% endblock content %}
layout.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Psychcore Pipeline</title>
<link rel="stylesheet" href="static/site.css"
</head>
<body>
{% include 'includes/_navbar.html' %}
<div class="container">
{% block body %}{% endblock %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js'></script>
</body>
</html>
In your layout.html you are defining a {% block body %}, however in your home.html you are using {% block content %}. Change one of these to match the other one and it should work.
To have jinja template read from a dict you need to change the syntax of all variables to the following in home.html:
{{ post['username'] }}