Trying to implement HTML Template into first Django project. Movies not showing - python

I am following along an online Python tutorial and I am have to create an HTML template in which creates a table for the end user to see the movies in the inventory. I have followed the teachers instructions step-by-by step but when I refresh the browser page, it only shows the class attributes that I listed in the HTML. The code that I wrote is below:
index.html file:
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Daily Rate</th>
</tr>
</thead>
<tbody>
{% for movie in movies %}
<tr>
<td>{{ movie.title }}</td>
<td>{{ movie.genre }}</td>
<td>{{ movie.number_in_stock }}</td>
<td>{{ movie.daily_rate }}</td>
</tr>
{% endfor %}
</tbody>
</table>
and the views.py file:
from django.http import HttpResponse
from django.shortcuts import render
from .models import Movie
def index(request):
movies = Movie.objects.all()
return render(request, 'index.html', {' movies': movies})
Here is what results on my web browser:
enter image description here
If someone knows why this is not working, any help would be awesome!

You seem to have a space where you are passing the context:
return render(request, 'index.html', {' movies': movies})
You need to replace ' movies' with 'movies', otherwise the variable will not be available with the correct name while rendering the template.

As the other user #le.chris mentioned, you seem to have a space where you are passing the context.
This would be the right context : return render(request, 'index.html', {' movies': movies}).
However, in your views file, I highly suggest having Class-based views, start by importing the ListView in this case and create a post_list.html or specify a template_name and since you are using movies as your context object, you also need to specify that in the context_object_name attribute. Maybe like this :
class MovieListView(ListView):
model = Movie
template_name = 'appname/index.html' #appname is the name of your app
context_object_name = 'movies'
ordering = # optional
paginate_by = 3
in your urls.py file of the app :
path('', MovieListView.as_view(), name='movie-index') #adjust the name as you please

Related

How to resolve "NoReverseMatch" Error in Django?

So I'm trying to create a table of hosts, and as one of the fields of that table include a clickable link to an update page. Which will pass the host_id to the update page. I was hoping someone could tell me what I'm doing wrong with regards to passing the correct parameter to upate/<host_id>. As I'm not quite sure as to how to fix the issue and make it so I can direct people via a clickable button in the table rendered to the appropriate update page. When I attempt to render the page with that added in I'm getting the following error:
NoReverseMatch at /website/home/
Reverse for 'update' with arguments '(1,)' not found. 1 pattern(s) tried: ['website/update/<host_id>']
Request Method: GET
Request URL: http://127.0.0.1:8000/website/home/
Django Version: 4.0.4
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'update' with arguments '(1,)' not found. 1 pattern(s) tried: ['website/update/<host_id>']
It is also spiecificlly pointing to the following line of code as the issue:
<td><a href="{% url 'update' beacon.host_id %}"</a>Issue Command</td>
This line is found in the following HTML segment.
Relevant HTML Section
{% for beacon in hosts %}
<tr>
<td>{{ beacon.host_id }}</td>
<td>{{ beacon.hostname }}</td>
<td>{{ beacon.internalIp }}</td>
<td>{{ beacon.externalIp }}</td>
<td>{{ beacon.current_user }}</td>
<td>{{ beacon.os }}</td>
<td>{{ beacon.admin }}</td>
<td><a href="{% url 'update' beacon.host_id %}"</a>Issue Command</td>
</tr>
{% endfor %}
My urls.py section looks like the following.
urls.py
urlpatterns = [
re_path('home/', views.home),
re_path('host-detailed', views.host_detailed),
re_path('update/<host_id>', views.update, name='update'),
]
Relevant Models.py
class Command_Node(models.Model):
host_id = models.ForeignKey(Beacon, on_delete=models.CASCADE)
current_commands = models.CharField(
choices=CHOICES, max_length=50, null=True)
def __str__(self):
return str(self.host_id)
Relevant Views.py
def home(request):
hosts = Beacon.objects.all()
return render (request, 'home.html', {'hosts':hosts})
def host_detailed(request):
return render (request, 'hosts-detailed.html')
def update(request, host_id):
host_id = Command_Node.objects.get(pk=host_id)
form = Command_Node(request.POST or None, instance=host_id)
if form.is_valid():
form.save()
return redirect('home.html')
return render (request, 'update.html', {'host_id':host_id,'form':form})
Try something like this:
Urls:
path('update/<int:pk>',views.update,name='update'),
Template
href="{% url 'update' pk = beacon.host_id %}"
As the other comment also mentioned, I don't think re_path is the way to go
How to pass an id to a view as an argument in Django?

Using django-auditlog, how can I display the 'actor_id' for a particular model?

I have created a simple Django application to display individual articles. These articles have a number of fields that users can edit. I am using the package 'django-auditlog' to log changes to these article models. So far, I have simply followed the auditlog installation doc to setup model history tracking (as well as enabling the middleware to allow 'actor_id' to be tracked). I have also added the example code that displays the most recent changes on the individual model pages as such:
<!-- History display -->
<div class="table-responsive">
<table id="history" class="table table-striped table-bordered">
<thead>
<tr>
<th>Actor</th>
<th>Field</th>
<th>From</th>
<th>To</th>
</tr>
</thead>
<tbody>
<!-- Human readable - change to '.changes_dict.' for proper logs -->
{% for key, value in article.history.latest.changes_display_dict.items %}
<tr>
<td>{{ article.history.latest.author_id }}</td>
<td>{{ key }}</td>
<td>{{ value.0|default:"None"|striptags|safe }}</td>
<td>{{ value.1|default:"None"|striptags|safe }}</td>
</tr>
{% empty %}
<p>No history for this item has been logged yet.</p>
{% endfor %}
</tbody>
</table>
</div>
As my code may suggest, I am trying to add an additional column to the history table to show who made the changes that are being displayed.
Is there an easy way to do this through auditlog, or will I have to create some kind of sql query to my sqlite auditlog db table to retrieve the 'author_id' field?
Thank you!
I figured out the answer after looking through the models file for Django AuditLog. It is not possible to pull the actor out directly from the history field of the model if you have created the history field using the AuditlogHistoryField() method as described in the django-auditlog tutorial.
Instead, I did the following:
In the views.py file
from auditlog.models import LogEntry
...
dal_log = LogEntry.objects.get_for_object(article)
...
context = {'article': article, 'logs': dal_log}
return render(request, "detail.html", context)
Then in my template, I was able to work with the log entries for the specified object (in my case, these were 'article' models). There may be a cleaner way, but this worked for me.

How to modify the view to only show the data to one assigned user?

Problem:
I would like to assign a bank statement for each user. Each user will log in using their username and password, and access their document. At the moment, one user can see the statement of all users.
Option 1:
I`ve added a manytomany relationship for the user to the model. When logged in on the Admin interface, I can assign the Bank Statement to the user.
Question:
What is the right way to define the views.py or the html file to only show the bank statement to the user logged-in.
models.py
class BankStatement(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='bs')
name = models.CharField(max_length=20)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
views.py
#login_required(login_url="/login/")
def bankstatement_detail(request, bankstatement_id):
bankstatement = BankStatement.objects.get(pk=bankstatement_id)
context = {
'bankstatement': bankstatement,
}
return render(request, 'administration/bankstatement_detail.html', context)
#login_required(login_url="/login/")
def index_bankstatement(request):
user = request.user
bankstatement = BankStatement.objects..filter(user=request.user)
context = {
'bankstatement': bankstatement,
}
return render(request, 'administration/bankstatement_detail.html', context)
bankstatement_detail.html
<div class="card-block table-border-style">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Date Created</th>
<th>Last Updated</th>
</tr>
</thead>
<tbody>
{% for bankstatement in bankstatements %}
<tr>
<td>{{ bankstatement.id }}</td>
<td>{{ bankstatement.name }}</td>
<td>{{ bankstatement.date_created }}</td>
<td>{{ bankstatement.last_updated }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
Many Thanks
I do not know if you are still working on this one, but
I do not agree with linking of the BankStatement to the User as ManyToMany. In my opinion, one user can have many statements, but one statement has only one user. So it is a one to many relationship defined by Foreign Key.
Let's fix the view:
#login_required(login_url="/login/")
def bankstatement_detail(request, bankstatement_id):
# this line forces to show the statement of the logged in user
user = request.user
bankstatement = BankStatement.objects.get(pk=bankstatement_id, user=user)
context = {'bankstatement': bankstatement,}
return render(request, 'administration/bankstatement_detail.html', context)

Retrieve data from database without using extra page

In my 'django' project, I need to retrieve / insert data from multiple tables of my (mysql)database. However because of the code I used, I had to use an extra .html page for each table operation. I want to be able to access multiple tables on a single html page. In order to better explain the situation, I write the relevant codes of the project below.
Project/views.py
def home_view(request, *args, **kwargs):
print(args, kwargs)
print(request.user)
return render(request, "home.html", {})
#login_required()
def admin_view(request, *args, **kwargs):
print(args, kwargs)
print(request.user)
return render(request, "adminPage.html", {})
#login_required()
def doctor_view(request):
return render(request, 'doctorPage.html', {'doctors': doctor_view()})
appointments/views.py
from django.views.generic import DetailView, ListView
class list_of_appointments(ListView):
model = Appointment
template_name = 'appointments/appointment_list.html'
class list_of_patients(ListView):
model = Patient
template_name = 'appointments/patient_list.html'
appointments/urls.py
urlpatterns=[
url(r'^appointment_list/$', list_of_appointments.as_view(), name='list1'),
url(r'^patient_list/$', list_of_patients.as_view(), name='list2')
]
So, in order to access the operations related to the tables, I have to use the following url code.
<a href={% url 'appointments:list2' %}>
Therefore, I can create a second html file and extract the data I want to extract from the database with this method.
{% for appointment in object_list %}
<tr>
<td>{{ appointment.patient.name }}</td>
<td>{{ appointment.doctor.name }}</td>
<td>{{ appointment.Date }}</td>
<td>{{ appointment.time }}</td>
<td>{{ appointment.province }}</td>
<td><a href="#">
<button type="button" class="btn btn-default"><span class="glyphicon glyphicon-pencil"
aria-hidden="true"></span>Edit
</button>
</a></td>
</tr>
{% endfor %}
But I want to do this database interaction on an existing html link (eg adminPage) without going to another link. Nowhere could I find out how to do this, can you help me? Thank you all!
If you want pass more than one model to ListView, you can override get_context_data method of MultipleObjectTemplateResponseMixin. But be carefull, it should be a QuerySet object. The example look like this:
views.py
from django.views.generic.list import ListView
from .models import FirstModel, SecondModel, ThirdModel
class MyListView(ListView):
template_name = 'my_app/what-ever.html'
model = Article
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['my_first_model'] = FirstModel.objects.all()
context['my_second_model'] = SecondModel.objects.all()
context['my_third_model'] = ThirdModel.objects.all()
return context
what-ever.html
{% for object in my_first_model %}
<h1>{{ object.title }}</h1>
<p>{{ object.pk }}</p>
{% endfor %}
You can find more information here.

Django - how to make a link in an html template open an app and pass a objects value as a parameter

Hello I have an app that displays some database information in a table. Inside of the html template I am making an edit link that I want to open another app(page viewLit) while passing a value to it's view. I have added my code below. My question is I am unsure of how to make this links url and pass the object data located inside circuit.circuitid along with it. I haven't been able to find the right way to code this yet and this is just how I thought that this should be done. If anyone has a better idea I am open to suggestions.
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}
myapp/myapp/urls.py
urlpatterns = [
path('viewLit/', include('viewLit.urls')),
]
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/circuitid.id', views.viewLit, name='viewLit'),
]
myapp/viewLit/views.py
def viewLit(request, circuitid):
#display records fields here
return HttpResponse("You are at the viewLit page!")
Have a look at the documentation:
Django documentation
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/(?P<circuit_id>\w+)', views.viewLit, name='viewLit'),
]
html- template:
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}

Categories

Resources