Django html page does not display a variable i passed in views - python

i am a beginner with Django and i encountered a problem. I wrote a code which allows me to add different products and categories from admin, and then display them on a html page. However, when i click on any of the displayed products i want my product description to be displayed in another html page. The first page is working just fine( product_list.html), however i am having trouble with the second one (product_detail.html).
urls.py ( without the imports):
urlpatterns = [
url(r'^category/(?P<categoryid>\d+)/$', views.product_list, name='product_list_by_category'),
#url(r'^list/(?P<id>\d+)/$', views.product_detail, name='product_detail'),
re_path('^$', views.product_list, name = 'product_list'),
url(r'^list/(?P<id>\d+)/$', views.product_detail, name='product_detail'),
]
views.py
def product_list(request, categoryid = 1): *this one is working*
categories = Category.objects.all()
products = Product.objects.all().filter(category_id=categoryid)
context = {'categories': categories,
'products': products
}
return render(request, 'shop/product_list.html', context)
def product_detail(request, id=1): *this one is not displaying anything*
productt = Product.objects.all().filter(id = id)
return render(request, 'shop/product_detail.html', {'product': productt})
product_detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{product.description}}
</body>
</html>
Do you have any idea why the page rendered by product_detail does not display anything?

#DanielRoseman is right, but to prevent an error in case there's no Product with that id, you have 3 options. The first one is to do a queryset and get the first element, then check if there is a result, like this:
productt = Product.objects.filter(id=id).first()
if productt is None:
# do something to let the user know the product doesn't exist
The second option is to wrap your get method arround a try except:
try:
productt = Product.objects.get(id=id)
except Product.DoesNotExist:
# do something to let the user know the product doesn't exist
The final option is to use get_object_or_404, which:
Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.
from django.shortcuts import get_object_or_404
productt = get_object_or_404(Product, id=id)

filter returns a queryset. Querysets don't have id or description attributes.
You need to use get to get an instance:
productt = Product.objects.get(id=id)

Related

is there any way to call a function(in another python file) and get the same return in Django view

I am trying to get a return from a function that is in similarity.py (function name returnTablewithURL) to Views.py. When I print the variable df in similarity.py it gives the output in dataframe. Like this:
Similarity (%)
https://en.wikipedia.org/wiki/The_quick_brown_f... 0.876818
https://knowyourphrase.com/the-quick-brown-fox 2.371295
I want to get the same output for fileupload function in views.py. So I tried to call the function from views (meaning from fileupload function) but it shows something in numbers. Output( with the help of print statement to check if it is same):
<function returnTableWithURL at 0x000001D3631311F0>
I have tried some other methods but in vain. It would be really helpful if i could use some suggestion and help
Views.py:
def fileupload(request):
# Handel file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
#Process for handeling the file snd store it on mongodb
newdoc = Document(docfile = request.FILES['docfile'])
#Contain process for extracting data in a file and storing them in DB as textfield
newdoc.fileData = request.FILES['docfile'].read()
newdoc.username = request.user
newdoc.save()
# Redirect to the document list after post
result(newdoc.fileData)
# Here i am trying to get the result from
# returnTableWithURL function. This function is in
# another python
dframe = returnTableWithURL
print(dframe)
return render(request, 'report.html',{'df':
dframe})
else:
form = DocumentForm() #A empty, unbound form
# Load documents for the list page
documents = Document.objects.filter(username=request.user)
# Render list page with the documents and the form
return render(request,
'home.html',
{'documents': documents, 'form': form})
Here is the function and python file. function takes an parameter.
Similarity.py
def returnTableWithURL(dictionary):
df = pd.DataFrame({'Similarity (%)':dictionary})
print(df)
return df
Here is the HTML page where I want to show the dataframe
report.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Plagirism Report</title>
</head>
<body>
{{ df }}
</body>
</html>
Alright, so i failed to do it in normal process like by calling the df variable but I succeded it using json. I followed this solution https://www.geeksforgeeks.org/rendering-data-frame-to-html-template-in-table-view-using-django-framework/
I hope it helps other

Multiple views in one url address in Django

The problem is this:
I have two classes Posts and Pubs in models.py, I need them to be displayed simultaneously on the main page,
I have in views.py file:
def pubs_list(request):
publications = Pubs.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'app/pubs_list.html', {'publications': publications})
def posts_list(request):
posts = Posts.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'app/posts_list.html', {'posts': posts})
in urls.py:
path('', views.posts_list, name='posts_list'),
# path('', views.pubs_list, name='pubs_list'),
accordingly, if we uncomment the second condition, then the first will work.
The question is, is it possible to make 2 views have one path, or is it somehow necessary to register in the view? Thanks.
No, each URL can only be handled by one view.
For the example in your question, it would be straight forward to make a single view that fetches the posts and publications.
def pubs_and_posts(request):
publications = Pubs.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
posts = Posts.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'app/pubs_.html', {'publications': publications, 'posts': posts})
You can use a unique view with both models:
urls.py
path('', views.posts_and_pubs, name='posts_and_pubs_list'),
views.py
def posts_and_pubs(request):
posts = Posts.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
publications = Pubs.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'app/posts_list.html', {'posts': posts, 'publications': publications})

Render html from a db field in Django

In my django project I have a model with a field that contain html code as text:
html_test = models.TextField()
for example in this field could be:
<html>
<header><title>This is title</title></header>
<body>
Hello world
</body>
</html>
I want to retrive this code and render dynamically showing the corresponding html page without create a file or save it on disk.
How can i render an html code in memory for display page and then destroy it?
I'm still not sure what your actual question is. You retrieve the model from the db and return the data to the user, just like anything else. For example, a view might look like this:
def my_view(request, pk):
obj = MyModel.objects.get(pk=pk)
return HttpResponse(obj.html_test)
Using jinja2 as the templating engine,
class YourClassName(generic.TemplateView):
template_name = 'your_template.jinja'
def get_context_data(self, **kwargs):
kwargs['html_data'] = MyModel.objects.get(pk=pk).html_test
return super(YourClassName, self).get_context_data(**kwargs)
In your your_template.jinja
<html>
<header><title>This is title</title></header>
<body>
{{html_data}}
</body>

Django and Folium integration

Django newbie here: my aim is to integrate Folium to an html page. so what I have at the moment:
polls/views.py
def show_map(request):
#creation of map comes here + business logic
m = folium.Map([51.5, -0.25], zoom_start=10)
test = folium.Html('<b>Hello world</b>', script=True)
popup = folium.Popup(test, max_width=2650)
folium.RegularPolygonMarker(location=[51.5, -0.25], popup=popup).add_to(m)
context = {'my_map': m}
return render(request, 'polls/show_folium_map.html', context)
polls/urls.py
urlpatterns = [
path('show_my_map', views.show_map, name='show_map'),
]
and show_folium_map.html
<h1>map result comes here</h1>
{{ my_map }}
problem is that I get the 'to_string' value of the map (I promise you I saw that coming). So how can I integrate the map in such way that I can actually see the map and also define the size?
In order to really include folium into custom django template you have to render your figure first before adding it to context (This will recursivly load all parts of the map into the figure). Afterwards in your template, you have to access header, html and script parts of figure seperatly by calling their render function. Additionally, those parts have to marked as "safe" by django template tag in order to allow html insertion. See example below.
Example:
views.py:
import folium
from django.views.generic import TemplateView
class FoliumView(TemplateView):
template_name = "folium_app/map.html"
def get_context_data(self, **kwargs):
figure = folium.Figure()
m = folium.Map(
location=[45.372, -121.6972],
zoom_start=12,
tiles='Stamen Terrain'
)
m.add_to(figure)
folium.Marker(
location=[45.3288, -121.6625],
popup='Mt. Hood Meadows',
icon=folium.Icon(icon='cloud')
).add_to(m)
folium.Marker(
location=[45.3311, -121.7113],
popup='Timberline Lodge',
icon=folium.Icon(color='green')
).add_to(m)
folium.Marker(
location=[45.3300, -121.6823],
popup='Some Other Location',
icon=folium.Icon(color='red', icon='info-sign')
).add_to(m)
figure.render()
return {"map": figure}
templates/folium_app/map.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{{map.header.render|safe}}
</head>
<body>
<div><h1>Here comes my folium map:</h1></div>
{{map.html.render|safe}}
<script>
{{map.script.render|safe}}
</script>
</body>
</html>
You can try the below way. I also had faced the same issue and it worked great for me.
views.py
def show_map(request):
#creation of map comes here + business logic
m = folium.Map([51.5, -0.25], zoom_start=10)
test = folium.Html('<b>Hello world</b>', script=True)
popup = folium.Popup(test, max_width=2650)
folium.RegularPolygonMarker(location=[51.5, -0.25], popup=popup).add_to(m)
m=m._repr_html_() #updated
context = {'my_map': m}
return render(request, 'polls/show_folium_map.html', context)
show_folium_map.html
{{ my_map|safe }}
You can get the html as a string by triggering the rendering on the (internal) parent of Map:
m = folium.Map()
html: str = m.get_root().render()
Note that this returns a full html page, so you may need to put it in an iframe.
Alternatively, you can render the head, body and script parts separately. That way you can put each part on your page where it belongs and you don't need an iframe:
m = folium.Map()
html_head: str = m.get_root().header.render()
html_body: str = m.get_root().html.render()
html_script: str = m.get_root().script.render()

How to have 2 Models/Views/Templates on one Page in Django?

I know this has probably been asked a 1000 times but I still for the life of me can't find a decent answer. Reading tutorials, Stack and even looking at GitHub for examples - nothing is helping or even guiding me in the right direction.
I have 2 separate Models/Views/Templates which each work beautifully on their own URLS.
I want these Models/Views/Templates to work on a single URL ie
url(r'^$', 'chrometask.views.index', name='home'),
(ie my homepage.)
How??? This seems to be way overly complicated for such a simple ask.
here is my views.py
items = Task.objects.all()
form = TaskForm(request.POST or None)
task_list = Task.objects.order_by('priority')
context_dict = { 'Tasks' : task_list}
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
return HttpResponseRedirect('')
return render_to_response('home.html', #Don't know how to render 2 html files or add the context_dict
locals(),
context_instance=RequestContext(request))
render_to_resonse can only take 3 arguments, and when I put the table inside 'home.html' with {% blockquote %} it wont show on the page.
<div class="collapsible-header"><i class="mdi-hardware-laptop-"></i>Title</a></div>
<div class="collapsible-body">
<div class="intro grey lighten-5">
{% block content %}{% endblock %} <--This is the table.html, which extends fine with {% entends 'home.html' %}-->
</br>
Please don't direct me to tutorials, These haven't resolved the issue, I would rather you spelt it out in layman's terms if possible, this may help drill the answer into my thick skull.
note - I am New to Django.
(*apologies for the frankness - this is really beginning to drive me up the wall)
You haven't said what you have tried to do to solve this, why you think it's "way overly complicated", or why it's causing you frustration.
The thing to understand is that a view is entirely responsible for a page, ie the view creates the entire response when a URL is requested. You can't have two views on a URL; that simply doesn't make sense.
But the other thing to understand is that templates and models are not in any way connected to any particular view. One view can render any number of templates, one, many, or even none; and any of those templates can involve any number of models from any number of apps.
So, if you wanted to include tasks in your home page, one approach is just to include the Tasks in the context dictionary in your view, and include the relevant code to your template to display them.
Now, if you're doing this in multiple views, then clearly you want to put that code somewhere sensible so that you Don't Repeat Yourself. The ideal place for this is an inclusion tag: you can wrap up the code that queries the latest tasks, and the template fragment that renders them, into a single tag which you can then use on your home page template.
Edit
The context is the second argument to render_to_response: the place where you've currently put locals(). That's a horrible pattern which I hate, and which is confusing you unnecessarily. Instead of using locals, put all the things you require for the context specifically into context_dict and pass that there instead.
(Also note you should use the render shortcut rather than render_to_response, which accepts the request as the first parameter and doesn't need all that mucking around with RequestContext.)
context_dict = { 'Tasks' : task_list, 'form': form}
...
return render(request, 'home.html', context_dict)
The code you have posted for your template is confusing. Is the table in table.html or home.html? If you pass "home.html" in your call to render, then it's home.html that will be rendered, not table. If you want to render table so that it extends home, then pass "table.html" in your call to render.
My Code ended up looking like
def home(request):
items = Task.objects.all()
form = TaskForm(request.POST or None)
task_list = Task.objects.order_by('priority')
context_dict = { 'Tasks' : task_list, 'form': form}
if form.is_valid():
save_it = form.save()
save_it.save()
return HttpResponseRedirect('')
return render(request, 'table.html', context_dict)
This has both models workig in one view.
def tutlist(request,tut):
model = Tutorial
model = Codetut
template_name = 'backpages/tutorial.html'
temp = Parts.objects.get(pk = tut)
model = temp.tutorial_set.all()
print(model)
temp = Parts.objects.get(pk = tut)
code = temp.codetut_set.all()
print(code)
context = {'model' : model ,'something': code}
return render(request, template_name,context)
i was having a similar problem i wanted to display two different views on a single template with a single url so i did something like this which worked well for me.

Categories

Resources