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.
Related
When I am filtering for my search bar I am getting this error. I am not sure what I am doing wrong here
Watching this tutorial: https://www.youtube.com/watch?v=llbtoQTt4qw&t=3399s
views.py
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people'
def get_context_data(self, **kwargs):
search_input = self.get.GET.get('search-area') or ''
if search_input:
context['people'] = context['people'].filter(name__icontains=search_input)
return context
people_list.html
{%if request.user.is_authenticated %}
<p>{{request.user}}</p>
Logout
{% else %}
Login
{% endif %}
<hr>
<h1>Interviewee Dashboard {{color}}</h1>
Add Candidates
<form method="get">
<input type = 'text' name = 'search-are'>
<input type = 'submit' value = 'Search'>
</form>
<table>
<tr>
<th> Item</th>
<th> </th>
</tr>
{% for people in people %}
<tr>
<td>{{people.name}}</td>
<td>View</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% empty %}
<h3>No items in list</h3>
{% endfor %}
</table>
There are some minor mistakes such as it should be self.request.GET.get('search-area'), also you haven't called the super() method, so try this view:
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people_list'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
search_input = self.request.GET.get('search-area', False)
if search_input:
context['people']= People.objects.filter(name__icontains=search_input)
return context
In the Html, the field name search-are and you are accessing in the view as self.request.GET.get('serach-area', False) kindly change its name to search-area` in the input tag of Html.
Also, class based views are generally written in PascalCase as they are classes of Python and requires their name to be written as model name as prefix and actual view name as suffix, so it should be PeopleListView.
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
I want to create a management page where an admin can delete users. I have succesfully made it list created users, but now i'm struggeling with how to create a deleteView to delete the user entirely from my django project.
Views.py
def index(request):
users = User.objects.all()
return render(request, 'EditUser.html',{'userlist':users})
def deletefunction(request,User =None):
object = User.objects.get(id=User)
object.delete()
return render(request,'EditUser.html')
Project urls.py
from edit_user.views import deletefunction
urlpatterns = [
path('admin/', admin.site.urls),
path('management', include('management.urls')),
path('management/create', include('signup.urls')),
path('management/edit', include('edit_user.urls')),
path('^delete/(?P<User>[0-9]+)/$', deletefunction, name='delete_view'),
]
HTML code
<div class="container">
{% for item in userlist %}
<tr>
<td>{{ item.username }}</td>delete
</tr>
{% endfor %}
</div>
As of right now when i'm trying to load my page i'm receiving this exception.
Reverse for 'deletefunction' not found. 'deletefunction' is not a
valid view function or pattern name.
def deletefunction(request, user_id):
object = User.objects.get(id=user_id)
object.delete()
users = User.objects.all()
return render(request,'EditUser.html', {'userlist': users})
and
<div class="container">
{% for item in userlist %}
<tr>
<td>{{ item.username }}</td>delete
</tr>
{% endfor %}
</div>
I think you should delete EditUser in href. Because you url in project urls.py(not EditUser urls ). So django looks EditUser app_name but they cant find.
Also you had not determineted 'User'.And you url name "delete_view" but you send view name.Can you change like this?Maybe work.
<td>{{ item.username }}</td>delete
I have an application which requests data based on certain parameters. I use two functions to handle the requests and then create two objects from the responses. I am able to iterate through each object individually and display the data of a particular object on my webpage, but when I try to use both functions simultaneously, only one function iterates through the object. It is my understanding that this issue has something to do with URL patterns, but I am not as to what the best approach would be. Below you will find my urlpatterns, my functions, and the HTML I use to access the view.
urls.py
urlpatterns = [
path('', views.customer, name='customer'),
path('', views.information, name='information'),
]
views.py
def customer(request):
for i, contact in enumerate(contactObj):
try:
contacts = contactObj
context = {'contacts': contacts}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
def information(request):
for i, ticket in enumerate(ticketObj):
try:
tickets = ticketObj
context = {'tickets': tickets}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
home.html
<tbody>
{% for ticket in tickets %}
<tr class="{% cycle 'row1' 'row2'">
<td> {{ ticket.id }} </td>
<td> {{ ticket.company.name }} </td>
<td> {{ ticket.summary }} </td>
</tr>
{% endfor %}
</tbody>
Your URL patterns should be different for every view. otherwise, it will always call the view which is defined above either you call it by customer or information
So your URL patterns should be
urlpatterns = [
path('customer/', views.customer, name='customer'),
path('information/', views.information, name='information'),
]
UPDATE
You don't have to create separate views for fetching objects from different tables to
show in a webpage
Create a single view and send as many objects in context dictionary.
def table_content(request):
...
# fetch objects here from model
contacts = Contact.objects.all()
tickets = Ticket.objects.all()
# set objects to context dictionary
context = {'contacts': contacts, 'tickets' : tickets}
return render(request, 'uccx/home.html', context)
Now in your template, you can easily loop over tickets and contacts
{% for ticket in tickets %}
<tr>
<td> {{ ticket.id }} </td>
...
</tr>
{% endfor %}
{% for contact in contacts %}
<tr>
<td> {{ contact.id }} </td>
...
</tr>
{% endfor %}
I have a model that has a ManyToManyField of Users:
models.py
class Excuse(models.Model):
students = models.ManyToManyField(User)
reason = models.CharField(max_length=50)
views.py
def excuse_list(request, block_id=None):
queryset = Excuse.objects.all().prefetch_related('students')
context = {
"object_list": queryset,
}
return render(request, "excuses/excuse_list.html", context)
Template (excuse_list.html)
...
{% for excuse in object_list %}
<tr>
<td>{{ excuse.reason }}</td>
<td>
{% for student in excuse.students.all %}
{{student.get_full_name}};
{% endfor %}
</td>
</tr>
{% endfor %}
...
How can I sort the User set (excuse.students.all) alphabetically by a User field, for example: user.last_name?
you can do this just changing your views.py with this:
queryset = Excuse.objects.all().prefetch_related(
Prefetch('students', queryset=User.objects.order_by('lastname')))
remember to import User model!
You can create a method in your Excuse model, that will return a sorted students set:
def get_sorted_students(self):
return self.students.all().order_by('last_name')
And then in your template use excuse.get_sorted_students instead of excuse.students.all
Alternatively, you could use a custom template tag to render the list of students.