Easiest way to display Django model data in html - python

I have data being stored in a Django model, and I want to display that data in my HTML file. What is the easiest way that I could do this? I am familiar with [this][1] question, but it does not help me because it is not very detailed and does not have a definite answer. Can someone please help me? My code is down below.
Django Model:
class userdetails(models.Model):
donations = models.IntegerField(blank=True, null = True,)
points = models.IntegerField(blank=True, null = True,)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
)
HTML where I want to display data from the model:
<div class="box">
<span class="value"> </span>
<span class="parameter">Points</span>
</div>
This is my view:
#login_required(login_url='/login/')
def dashboard(request):
id = request.user.id
data= userdetails.objects.get(id=id)
return render(request,'dashboard.html',{'data':data})
The error I keep getting:
DoesNotExist at /dashboard/
userdetails matching query does not exist.
Has something to do with data= userdetails.objects.get(id=id) in my views.

you need to create a view to retreive the data you need from your model :
views.py :
from .models import userdetails
from django.shortcuts import render
def get_data(request):
my_data = userdetails.objects.all() #for all the records
one_data = userdetails.objects.get(pk=1) # 1 will return the first item change it depending on the data you want
context={
'my_data':my_data,
'one_data':one_data,
}
return render(request, 'get_data.html', context)
add the the view to urls.py :
url.py :
from .views import get_data
urlpatterns = [
path('get_data/', get_data, name='get_data'),
]
create get_data.html in the templates folder :
get_data.html : for the list
{% block content %}
{% for x in my_data %}
{{x.name }}
{% endfor %}
{% endblock content %}
for the item :
{% block content %}
{{one_data}}
{% endblock content %}
the best practice is to create a list view and a detail view so if you dont know how tell me and i will show you

You need to add a function to the views.py file and render the HTML file to a URL that should be there in Url Patterns.
For example:
This is a sample model:
class C(models.Model):
name = models.CharField(max_length=125, null=True)
phone = models.CharField(max_length=125, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
This is my views.py
from .models import *
def home(request):
c = C.objects.all()
return render(request, "<app_name>/index.html", {'c': c})
This is my urls.py
from . import views
urlpatterns = [
path('home/',views.home),
]
This is my part of HTML file where I will show the data
{% block content %}
<h2>{{c.name}}</h2>
{% endblock content %}

Related

why I can not link these two pages in my django project

I have 2 models named "developer" and "skill". I made a page for all the developers that have their respective information. Now, I want to make a page that lists all the developers with links that navigate to their respective information page.
The page that shows all the developers' URLs is 'developers/' and its name is "developers". The URL of the second page is 'developers/id' and its name is developer, however it instead navigates to 'developers/developers/id'.
I tried the page that shows the information of a certain developer and it was ok but I have problem with this one cause it won't navigate.
here are my codes :
views.py
from django.shortcuts import render
from .models import Developer, Skill
# Create your views here.
def show_developers(request):
query = Developer.objects.all()
context = {'devs': query}
return render(request, 'users/devs.html', context=context)
def show_single_developer(request, pk):
query = Developer.objects.get(id=pk)
context = {'dev': query}
return render(request, 'users/single_dev.html', context=context)
models.py
from django.db import models
# Create your models here.
class Skill(models.Model):
choices = (
('Beginner', 'Beginner'),
('Junior', 'Junior'),
('Senior', 'Senior'),
)
name = models.CharField(max_length=50)
level = models.CharField(choices=choices, max_length=10)
class Developer(models.Model):
full_name = models.CharField(max_length=50)
username = models.CharField(max_length=50)
intro = models.TextField(blank=True, null=True)
image = models.ImageField()
skills = models.ForeignKey(Skill, on_delete=models.CASCADE)
urls.py
from django.urls import path
from .views import show_developers, show_single_developer
urlpatterns = [
path('developers/', show_developers, name='developers'),
path('developers/<str:pk>/', show_single_developer, name='developer'),
]
devs.html
{% include 'navbar.html' %}
<table>
<tr>
<th>FullName</th>
<th>Username</th>
<th>details</th>
</tr>
{% for dev in devs %}
<tr>
<td>{{dev.full_name}}</td>
<td>{{dev.username}}</td>
<td>View</td>
</tr>
{% endfor %}
</table>
{% include 'footer.html' %}
single_dev.html
{% include 'navbar.html' %}
<h2>{{dev.full_name}}</h2>
<hr>
<h3>Intro</h3>
<h4>{{dev.intro}}</h4>
{% for skill in dev.sills.all %}
<div>
<p>{{skill.name}}</p>
<p>{{skill.level}}</p>
</div>
{% endfor %}
{% include 'footer.html' %}
TraceBack Section
and I add the structures of this app too
Error page

How to return single object in a Django model and view

I would like to return a very basic, single paragraph from a model but I don't know how or which is the best approach. It's a simple description textField (maindescription) that I would like to be able to change in the future instead of hard-coding it. It has to be simple way but I just could find a good example. Would appreciate any help on how to properly write the view and retrieve it in the template.
model.py
from autoslug import AutoSlugField
from model_utils.models import TimeStampedModel
from time import strftime, gmtime
# Receive the pre_delete signal and delete the file associated with the model instance.
from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver
class Song(models.Model):
author = models.CharField("Author", max_length=255)
song_name = models.CharField("Song Name", max_length=255)
slug = AutoSlugField("Soundtrack", unique=True, always_update=False, populate_from="song_name")
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
audio_file = models.FileField(upload_to='mp3s/', blank=True)
def __str__(self):
return self.song_name
class MainDescription(models.Model):
main_description = models.TextField()
slug = AutoSlugField("Main Description", unique=True, always_update=False, populate_from="main_description")
def __str__(self):
return self.main_description
view.py
from django.views.generic import ListView, DetailView
from .models import Song, MainDescription
class SongListView(ListView):
model = Song
# Overwrite the default get_context_data function
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add extra information here, like the first MainDescription Object
context['main_description'] = MainDescription.objects.first()
return context
admin.py
from django.contrib import admin
from .models import Song, MainDescription
admin.site.register(Song)
admin.site.register(MainDescription)
urls.py
from django.urls import path
from . import views
app_name = "music"
urlpatterns = [
path(
route='',
view=views.SongListView.as_view(),
name='list'
),
]
song_list.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<p>{{ main_description.main_description }}</p>
</div>
<ul class="playlist show" id="playlist">
{% for song in song_list %}
<li audioURL="{{ song.audio_file.url }}" artist="{{ song.author }}"> {{ song.song_name }}</li>
{% endfor %}
</ul>
{% endblock content %}
</div>
It looks like you're trying to add extra context to the SongListView
class SongListView(ListView):
model = Song
# Overwrite the default get_context_data function
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add extra information here, like the first MainDescription Object
context['main_description'] = MainDescription.objects.first()
return context
Then in your template you could do something like this
<p>{{ main_description.main_description }}</p>
For more information about that from the docs, you can find it here

NoReverseMatch at /post/1/log/ Reverse for 'log-create' with keyword arguments '{'post_id': ''}' not found

I have a Post model with a whole bunch of posts. I also have a log model which has a foreign key field to the Post model. Essentially the Log model stores log entries for the Posts in the Post model (basically Post comments). Everything was going great. I have been using CBV for my post models and I used a CBV to List my log entries. I then added a link to redirect me to the Log CreateView using the following anchor tag:
<a class="btn" href="{% url 'log-create' post_id=logs.post_id %}">Add Entry</a>
When the NoReverse errors started occuring. When I change the log.post_id to 1, the page loads correctly. This leads me to believe that the log.post_id is not returning any value. Another thought that I had was that because this anchor tag was on the LogListView there were multiple log entries so it didn't know which post_id to use. But I used the get_queryset function on this view to make sure that only logs related to a single post are returned. In my mind the log.post_id should work.
My models are:
class Post(models.Model):
title = models.CharField(max_length=100, blank=True)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
overview = models.TextField(blank=True)
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.id})
def __str__(self):
return self.title
class Log(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
log_entry = models.TextField(max_length=500, blank=True)
log_author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
My Views:
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, CreateView
from .models import Post, Log
from django.http import HttpResponseRedirect
from django.contrib.auth.mixins import LoginRequiredMixin
class LogListView(ListView):
model = Log
template_name = 'blog/log_entries.html'
context_object_name = 'logs'
ordering = ['-date_posted']
def get_queryset(self):
self.post = get_object_or_404(Post, log=self.kwargs['pk'])
return Log.objects.filter(post=self.post)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(LogListView, self).get_context_data(**kwargs)
# Add in a QuerySet of all images related to post
context['post'] = Post.objects.all()
return context
class LogCreateView(LoginRequiredMixin, CreateView):
model = Log
fields = [
'log_entry'
]
def form_valid(self, form):
form.instance.log_author = self.request.user
post = Post.objects.get(pk=self.kwargs['post_id'])
return super().form_valid(form)
My urls.py
from django.urls import path, include
from . import views
from .views import LogListView, LogCreateView
urlpatterns = [
path('', PostListView.as_view(), name='blog-home'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/log/', LogListView.as_view(), name='log-list'),
path('post/<int:post_id>/log/new/', LogCreateView.as_view(), name='log-create'),
]
And Lastly, my template:
{% extends "blog/base.html"%}
{% block body_class %} home-section {% endblock %}
{% block content %}
<div class="container">
<h2>Log Entries</h2>
{% for log in logs %}
<div class="row">
<article class="content-section">
<div class="article-metadata log-metadata">
<a class="mr-2" href="{% url 'profile' user=log.log_author %}">{{ log.log_author }}</a>
<small class="text-muted">{{ log.date_posted|date:"d F Y" }}</small>
{% if request.user.is_authenticated and request.user == log.log_author %}
<ion-icon name="trash"></ion-icon>
{% endif %}
</div>
<p class="">{{ log.log_entry }}</p>
</article>
</div>
{% endfor %}
<a class="btn" href="{% url 'log-create' post_id=logs.post_id %}">Add Entry</a>
</div>
{% endblock content %}
I think I am correctly passing a parameter to the url. this is evident from when I make post_id=1. But I am not sure I am calling it correctly. Any help on this issue would be great thanks.
UPDATED: I edited my context_object_name in my LogListView to logs to make the for loop less confusing. Essentially I am trying to get one anchor tag at the bottom of all the log entries to redirect to the Add entry page.
I suggest an approach that renders a link only if there are objects available, using the first element:
</article>
</div>
{% if forloop.first %}<a class="btn" href="{% url 'log-create' post_id=log.post.id %}">Add Entry</a>{% endif %}
{% endfor %}
This log.post.id means get id of post object (foreign key) of log object.

How do you create links using slugfield in Django generic listview class?

How to you create links (i.e. href) using SlugField for the output of Django's ListView generic class? Right now I can list all persons in the database using the code below but I want links using slug when clicked will show the person's description.
models.py
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
slug = models.SlugField(max_length=50)
description = models.TextField()
views.py
class PersonList(ListView):
model = Person
person_list.html
<ul>
{% for person in object_list %}
<li>{{ person.first_name }}&nbsp{{ person.last_name }}</li>
{% endfor %}
</ul>
You don't have to do anything in the list view. You need to add the URL to urls.py and make a detail view for your person. Then in the template reference the url and pass the slug:
app/urls.py:
from . import views
urlpatterns = [
# ... other urls
url(
r'^person/(?P<slug>[a-z0-9-]+)$', # Match this
views.PersonDetailView.as_view(), # Call this view
name='person_detail' # Name to use in template
)
]
app/views.py:
from django.views import generic
from .models import Person
class PersonDetailView(generic.DetailView):
model = Person
app/templates/app/person_list.html:
<ul>
{% for person in object_list %}
<li>{{ person.first_name }}&nbsp{{ person.last_name }}</li>
{% endfor %}
</ul>
See why this works here (look for slug).

Django, splitting a filter into separate links

I am trying to create a sort of an invoice system and I've created a model with the ForeignKey as the user. I made a custom view where I filter invoices by the current user. I need the filter to actually separate the invoices so I can create links to the actual invoice. Query and loop is my first instinct, but I just can't figure out how to do this in Django.
# models.py
class invoice(models.Model):
date = models.DateTimeField(default=datetime.now, blank=True)
bill_to = models.ForeignKey(settings.AUTH_USER_MODEL)
service = models.CharField(max_length="50", choices=serviceChoice, default='')
price = models.CharField(max_length="3"
# views.py
def invoicelist(request):
current_user = request.user
current_user = current_user.id
p =list(invoice.objects.filter(bill_to=current_user))
return render_to_response('invoice-list.html', {'invoice':p})
I call {{ invoice }} in invoice-list.html and it's a list of ALL invoices. If I try to use a for loop, it just lists the entire list over and over. I need them to be linkable to the appropriate invoice. Part of me feels like I'm going about this all wrong.
See get_absolute_url()
<!-- File: invoice-list.html -->
{% for invoice in invoices %}
{{ invoice.id }}
{% endfor %}
Note: Correction for your models.py & views.py:
# File: models.py
class Invoice(models.Model):
date = models.DateTimeField(default=datetime.now, blank=True)
bill_to = models.ForeignKey(settings.AUTH_USER_MODEL)
service = models.CharField(max_length="50", choices=serviceChoice, default='')
price = models.CharField(max_length="3"
# File: views.py
def invoice_list(request):
current_user = request.user.id
invoices = Invoice.objects.filter(bill_to=current_user)
return render_to_response('invoice-list.html', {'invoices':invoices})
Alternative (Optional):
You can also consider using url reverse. For example:
<!-- File: invoice-list.html -->
{% for invoice in invoices %}
{{ invoice.id }}
{% endfor %}
Provided you have the url configured correctly, for example:
# File: urls.py
urlpatterns = [
url(r'^invoices/$', views.invoice_list, name='invoice-list'),
url(r'^invoice/(?P<id>\d+)/$', views.invoice_detail, name='invoice-detail'),
]

Categories