Django: Display model values in table - python

I am a newbie to django and need some help. I have a created a vaguely functioning website. I have a model which looks as follows;
from django.db import models
class InductiveSensors(models.Model):
Part_No = models.CharField(max_length=250)
Manufacturer = models.CharField(max_length=250)
Sn = models.CharField(max_length=250)
AssuredSn = models.CharField(max_length=250)
def __str__(self):
return InductiveSensors.Manufacturer
There are a couple of pages. one which gives me a list of all items in the database
{% extends "ESensFind/header.html" %}
{% block content %}
{% for InductiveSensors in object_list %}
<h5>{{ InductiveSensors.Manufacturer}}<a
href="/Inductive_Search/{{InductiveSensors.id}}">
{{InductiveSensors.Part_No}}</a></h5>
{% endfor %}
{% endblock %}
When the {{InductiveSensors.Part_No}} link is clicked it opens up another page. On which I would like to display this database entry in a table with the information of
Part_No = models.CharField(max_length=250)
Manufacturer = models.CharField(max_length=250)
Sn = models.CharField(max_length=250)
AssuredSn = models.CharField(max_length=250)
my urls look like:
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from Inductive_Search.models import InductiveSensors
urlpatterns = [
url(r'^$',ListView.as_view(queryset=InductiveSensors.objects.all().order_by
("Manufacturer") #THIS PAGE IS THE LIST OF ALL DATABASE ENTRIES#
[:25],template_name="Inductive_Search/Inductive_Search.html")),
url(r'^(?P<pk>\d+)$', ListView.as_view(model= InductiveSensors,
template_name = 'Inductive_Search/SensorInfo.html')) #THIS OPENS UP A NEW
INDEX PAGE AFTER A PARTICULAR DATABASE ENTRY LINK IS CLICKED#
is the 2nd url code correct to work in conjunction with "SensorInfo.html"? In "SensorInfo.html" i have this code, which I would think should display even just the manufacturer information in a header but it displays nothing.
{% extends "ESensFind/header.html" %}
{% block content %}
<h5>{{ InductiveSensors.Manufacturer}}</h5>
{% endblock %}
Essentially what I am trying to do is get SensorInfo.html to display the values from my model, relating to that particular index in a table on my webpage. Any help would be appreciated. Thanks

The "right" solution is to write detail view (by deriving from DetailView), when in the template you can access the underlying object using get_object() or .object.
If you want to implement it quick and dirty, you have to access the pk argument and using it get the model instance, and pass it as part of the context data.
I suggest you dig into documentation, the django tutorial is good place to start (https://docs.djangoproject.com/en/2.0/intro/tutorial01/#writing-your-first-django-app-part-1) or read on class based views here https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-display/

So would a solution be something like the following to urls.py?
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from Inductive_Search.models import InductiveSensors
urlpatterns = [
url(r'^$',
ListView.as_view(queryset=InductiveSensors.objects.all().order_by
("Manufacturer")
[:25],template_name="Inductive_Search/Inductive_Search.html")),
url(r'^(?P<pk>\d+)$', DetailView.as_view(model= InductiveSensors,
template_name = 'Inductive_Search/SensorInfo.html'))
]
and in the template
{% extends "ESensFind/header.html" %}
{% block content %}
<h5>{{ get_object() }}</h5>
{% endblock %}

Related

How do I display a Django form correctly using ListView

I am writing a simple app to track sales leads based on the Django tutorial "Writing your first Django app" (https://docs.djangoproject.com/en/4.0/intro/tutorial01/). Everything works well except for displaying a ListView of the existing leads.
Here are the relevant python snippets:
Leads/models.py
class Leads(models.Model):
id = models.IntegerField(primary_key=True)
last = models.CharField(max_length=32)
first = models.CharField(max_length=32)
config/urls.py
urlpatterns = [
# Django admin
path('admin/', admin.site.urls),
# User management
path('accounts/', include('allauth.urls')),
# Local apps
path('leads/', include('leads.urls'))
leads/urls.py
app_name = 'leads'
urlpatterns = [
path('', LeadsListView.as_view(), name='list'),
path('<int:pk>/', LeadsDetailView.as_view(), name='detail'),
]
leads/views.py
class LeadsListView(ListView):
model = Leads
template_name = 'leads/list.html'
context_object_name = 'leads_list'
def get_queryset(self):
return Leads.objects.order_by('id')
class LeadsDetailView(DetailView):
model = Leads
template_name = 'leads/detail.html'
The link in the 'home.html' template, which displays a menu option correctly:
Leads
And finally, the 'list.html' template that does not display at all. Instead of showing the list of leads, it remains on the home page.
{% block content %}
{% for lead in lead_list %}
<div class="lead-entry">
<h2>{{ lead.fname }} {{ lead.lname }}</h2>
</div>
{% endfor %}
{% endblock content %}
I'm missing something fundamental here....
There are some minor mistakes such as:
Issue
The context_object_name='leads_list, and you have defined in your template file as lead_list, missed the s.
Your Model field's name is first and last, not fname and lname.
Solution:
Try this out in your template:
{% block content %}
{% for lead in leads_list %}
<div class="lead-entry">
<h2>{{ lead.first }} {{ lead.last }}</h2>
</div>
{% endfor %}
{% endblock content %}
I have changed lead.fname to lead.first and lead.lname to lead.last and also add s to lead_list, it is now leads_list.
Note: Models in django doesn't require its name in plural form, it would be better if you only give name model name Lead rather than Leads, as django itself adds s as the suffix.
Note: If you are overriding the default AutoField generated by django which is id, so you must override it with AutoField[django-doc] rather than making IntegerField primary key.

Django show same content (of a model) in sidebar of every page (also in different apps)

I have two apps: blog and mysite.
In the project folder, I have a template which includes a sidebar template. This sidebar is shown on every page of the project (index pages, mysite pages, blog pages).
One part of this sidebar should show a list of the latest x blog entries (independent of the page where the user is).
blog/models.py
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=264)
text = RichTextField(config_name='detail_text_field', default='')
created_date = models.DateTimeField(default=timezone.now)
blog/views.py
class LatestBlogEntriesListView(ListView):
model = Post
template_name = 'blog/_latest_blog_entries_list.html'
def get_queryset(self):
return Post.objects.all().order_by('created_date')[-3:]
sidebar.html
<div class="row">
{% include 'blog/_latest_blog_entries_list.html' %}
</div>
_latest_blog_entries_list.html
<h4>Latest Blog Entries</h4>
{% for post in objects %}
{{ post.title }}
{% endfor %}
Unfortunately, this does not work. My sidebar only shows the h4 "Latest Blog Entries", but not the posts. How can I do this?
Any help is highly appreciated!
I found to use a context processor, as described in this post: https://dev.to/harveyhalwin/using-context-processor-in-django-to-create-dynamic-footer-45k4
This allows to access a context variable within all pages.
When using ListView the default object is called object_list. Try changing your code to this:
{% for post in object_list %}
{{ post.title }}
{% endfor %}
You can also change this variable name in the view, so that when you catch it on the template, it's a custom name.
class LatestBlogEntriesListView(ListView):
model = Post
template_name = 'blog/_latest_blog_entries_list.html'
context_object_name = "your_new_object_name"

How can I lists all the products according to their foreign key?

I am working on my first eshop website using django framework and I got stuck on a problem.
I have created a general model for different kinds of products (like laptops, books etc.). Each product that is added to the website can be found by on its foreign key that links that product to a specific category.
The question is how can I display on laptops.html only the products that have the foreign key which points to the right category? Like, to display only the products from laptops category.
Thank you very much for your time!
EDIT:
in urls:
urlpatterns=[
path('', views.HomePage.as_view(), name='home'),
path('ComputerScience/', views.ComputerScience.as_view(), name='computer_science'),
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list')]
In computerscience.html I render all the cateogries.
Here in views.py I have the two controllers, first for categories and second for laptops for instance.
views.py
class ComputerScience(ListView):
model = ComputerScienceCategory
template_name = "computer_science.html"
context_object_name = "category"
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
# If you wish to still keep the view only for specific category use below line
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk'))
queryset = queryset.filter(category=category)
return queryset
Here I have the template where I want to display all categories.
computer_science.html
<div class="computerScienceContent" id="slide">
{% for cat in category %}
<a href="{% url 'category_products_list' category.pk %} " id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Here is laptops html, where I'd like to have the whole products displayed.
laptops.html
{% extends 'index.html' %}
{% block title %}
<title>Laptops</title>
{% endblock %}
{% block cont2 %}
{% endblock %}
My main goal is that to have a page (computerscience.html) where I have displayed a list with all available categories and when you click on one category, to redirect you to another page where you have listed all the products that belongs to that category.
This is the error that has been thrown to me:
Reverse for 'category_products_list' with arguments '('',)' not found. 1 pattern(s) tried: ['category/(?P<category_pk>[0-9]+)/list\\-products/$']
You should override get_queryset to filter your objects. Also as you are writing a view for a specific instance of category you would end up writing a lot of views, also when a new category would be added this would be very tedious you should use one view for all categories instead. Try this:
from django.shortcuts import get_object_or_404
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk')) # Assuming category_pk will be passed in url
# If you wish to still keep the view only for specific category use below line
# category = get_object_or_404(ComputerScienceCategory, pk=<pk-of-category-here>)
queryset = queryset.filter(category=category)
return queryset
To pass the categories primary key in the url you need to do something as follows:
In your urls.py:
urlpatterns = [
...
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list'),
...
]
Now in the page where you display all categories:
{% for cat in category %}
<a href="{% url 'category_products_list' cat.pk %}" id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Also you write id="aBar" but this line is in a loop meaning you would end up with multiple same ids you should use a class instead.

Django: List and Display Data from DB

I found a code that the urls in django can contain a model, so it can display a db values directly to html, but when i tried it, i got some error in the urls because this code still using patterns, is it possible doing this thing in a newer django?
The Url
from django.views.generic import ListView
from django.conf.urls import patterns, url
urlpatterns = patterns("myapp.views",
url(r'^dreamreals/', ListView.as_view(
template_name = "dreamreal_list.html")),
model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
The HTML
{% extends "main_template.html" %}
{% block content %}
Dreamreals:<p>
{% for dr in object_list %}
{{dr.name}}</p>
{% endfor %}
{% endblock %}
I'm pretty sure all you've entered are kwargs of ListView.as_view() method.
So instead of doing
ListView.as_view(
template_name = "dreamreal_list.html")),
model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
Which is actually syntaxly incorrect, do :
ListView.as_view(
template_name = "dreamreal_list.html",
model = Dreamreal,
context_object_name = ”dreamreals_objects”
)
Second error, you're setting the context_object_name to dreamreals_objects, but in your template you're iterating over object_list.
But this method is not really "pretty" and you should really make a views.py with your views and then the urls.py should only care about making a route.
As pointed in comments, django 2.1+ no longer use urlpatterns but path : https://docs.djangoproject.com/en/2.1/topics/http/urls/#example

I am not able to save the form data to databse in django

I want to add data through form and see it queried in my template
blog url:
urlpatterns = [
url(r'^admin/',admin.site.urls),
url(r'^blog/',include('content.urls',)),
]
content url:
urlpatterns = [
url(r'^add/$', views.add_content, name='content'),
]
models.py
from django.db import models
class AddContent(models.Model):
content_name = models.CharField(max_length=100, default='', blank=False, unique=True)
def __str__(self):
return self.content_name
forms.py
from django import forms
from .models import AddContent
class AddContentForm(forms.ModelForm):
class Meta:
model = AddContentModel
fields = [
"content_name",
]
views.py
def add_content(request):
form = AddContentForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect("/blog/content/")
content_data = AddContent.objects.all()
context = {
"form":form,
"content":content_data,
}
return render(request, "add_content.html", context)
def view_content(request):
view_data = AddContent.objects.all()
context = {
"show_content":view_data,
}
return render(request, 'show_content.html', context)
templates:
add_content.html
{% extends 'base.html' %}
{% block content %}
<form method='POST' action="/blog/content/">
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Add Content'/>
<h3>Recent content</h3>
{% for show in show_content %}
<p>{{ show.content_name }}</p>
{% endfor %}
{% endblock %}
The form data is not being saved, when I add it through admin interface it gives the result but form fails.
(this is just some useless content that I am writing in the bracket, stackoverflow didn't allow me posting as it looks like my post is mostly code; please add more details it said but i think the code has lot of details and i cant write anything just for the sake of length)
Your model form should look like this
from django import forms
from .models import AddContent
class AddContentForm(forms.ModelForm):
class Meta:
model = AddContent
fields = [
"content_name",
]
You've defined the wrong model name in the Meta class of model form. It should be AddContent not AddContentModel
I'm new to django too, but don't you need to specify the request inside the functions in views.py like :
def add_content(request):
if(request.method == 'POST'):
# rest of code here
Your form does not post to the view that saves the data; it posts directly to the view_content view, which ignores the data completely.
You can set the form action to "." to get it to post back to the same view that rendered it.
(As an additional point, you should avoid hard-coding URLs. Use the {% url %} tag in templates, and the reverse() function in views, to output URLs based on view names.)
First :
Correct the redirect() in your form.
return redirect("add_content", request.POST= None)
Second : you need to specify a URL for the content view : view_content
url(r'^content/$', views.view_content, name='content'),
And You need a template to render content (show_content.html :
{% extends 'base.html' %}
{% block content %}
<h3>Recent content</h3>
{% for show in show_content %}
<p>{{ show.content_name }}</p>
{% endfor %}
{% endblock %}
Edit :
Your form is not well defined. I edit my answer to make it complete :
You have to correct the model in your form (AddContent not AddContentModel) :
class Meta:
model = **AddContent**
fields = [
"content_name",
]

Categories

Resources