Django - Data from view not rendered in template - python

I'm having quite some troubles understanding how variables are passed to templates in Django, I'm new so keep this in mind.
My problem is that, when the URL is loaded data from databases can't be rendered except for the user(request.user.username) which is strangely loaded.
I even tried to declare variables inside the view's def but even them are not rendered
The model is imported inside the views.py.
My idea is that, since the user from request.user is loaded, there must be some problem with loading the database model, but this doesn't explain why even freshly declared variables inside the view's def are not passed.
In the /admin page all the models work fine.
Below are the fragments of my code, they should be enough to understand the problem, if not I can upload other parts.
Thank you in advance.
views.py:
def load_main(request):
diet_list = DietTable.objects.all()
return render(request, 'main/main.html',
{
'diet_list': diet_list,
'user': request.user.username,
})
part in the main.html:
<body>
...
<header>
...
</header>
...
{% block content %}
<strong>
{{ user }}
{% for element in diet_list %}
{{ element }}
{% endfor %}
</strong>
{% endblock %}
...
</body>
urls.py:
from django.urls import path, include
from main import views
urlpatterns = [
path('', views.load_main, name='main_view'),
]
models.py
...
class DietTable(models.Model):
diet_id = models.AutoField(primary_key=True) # to not use the default 'id; given by django
dietName = models.CharField(max_length=50)
dietType = models.ForeignKey(DietTypes, on_delete=models.PROTECT)
startDate = models.DateTimeField()
dayLength = models.IntegerField()
def __str__(self):
return str(str(self.dietName) + "(" + str(self.dayLength) + ")")
...

Related

Class Based Views filtering with "def get_queryset(self):" - Assistance with solving issues

I am trying to filter Data in my Web application and having issues to make it work properly.
My application has User model, to whom I assign different programs. Each program contain different exercises.
Program Model:
class Program(models.Model):
patient = models.ForeignKey(User, on_delete=models.CASCADE, default=0)
program_name = models.CharField(max_length=1000, default="")
date_posted = models.DateTimeField(default=timezone.now)
Program View:
class ProgramListView(ListView):
model = Program
template_name = 'program/prog.html'
context_object_name = 'programs'
def get_queryset(self):
return Program.objects.filter(patient=self.request.user)
Program Template:
{% extends "program/base.html" %}
{% block content %}
<h3> Please Choose your Program according to your Plan</h3>
{% for program in programs %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'program-detail' program.id %}">Program Name - {{ program.program_name }}</a>
</div>
<p class="article-content">Date Posted - {{ program.date_posted }}</p>
</div>
</article>
{% endfor %}
{% endblock content %}
Exercise Model:
class Exercise(models.Model):
program = models.ForeignKey(Program, on_delete=models.CASCADE, default=0)
date_posted = models.DateTimeField(default=timezone.now)
name = models.CharField(max_length=1000, default="")
description = models.TextField(default="")
load_share = models.TextField(default="")
breath_method = models.TextField(default="")
recovery_method = models.TextField(default="")
measure_method = models.TextField(default="")
notes = models.TextField(default="")
extra_info = models.TextField(default="")
reps = models.PositiveSmallIntegerField(default=0)
sets = models.PositiveSmallIntegerField(default=0)
Exercises View (ProgramDetailView):
class ProgramDetailView(DetailView):
model = Exercise
context_object_name = 'exercises'
def get_queryset(self):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
return Exercise.objects.filter(program=program_num)
Exercises Template:
{% extends "program/base.html" %}
{% block content %}
<h3> Program Exercises List</h3>
{% for exercise in exercises %}
<h3>{{ exercise.name }}</h3>
<h3>{{ exercise.description }}</h3>
{% endfor %}
{% endblock content %}
The Url's:
from django.urls import path
from .import views
from .views import ProgramListView, ProgramDetailView
urlpatterns = [
path('', views.home, name='web-home'),
path('about/', views.about, name='web-about'),
path('programs/', ProgramListView.as_view(), name='web-programs'),
path('programs/<int:pk>/', ProgramDetailView.as_view(), name='program-detail'),
My Program page works well, it shows me all the different programs the User was assign with.
Now, when I try to see the Program exercises (connects to the DetailView), it doesnt work.
I am trying to get the PK of the program and filter it with the help of the
get_object_or_404
The issues I encounter:
Only "pk=1" works (only the first program within the list), it shows me this error though -
TypeError at /programs/1/
'Exercise' object is not iterable
Request Method: GET
Request URL: http://127.0.0.1:8000/programs/1/
Django Version: 3.1
Exception Type: TypeError
Exception Value:
'Exercise' object is not iterable
Exception Location: C:\Users\shai3\Python\lib\site-packages\django\template\defaulttags.py, line 167, in render
Python Executable: C:\Users\shai3\Python\python.exe
Python Version: 3.8.5
Python Path:
['C:\\Users\\shai3\\PycharmProjects\\website',
'C:\\Users\\shai3\\Python\\python38.zip',
'C:\\Users\\shai3\\Python\\DLLs',
'C:\\Users\\shai3\\Python\\lib',
'C:\\Users\\shai3\\Python',
'C:\\Users\\shai3\\Python\\lib\\site-packages']
Server time: Thu, 03 Sep 2020 12:04:29 +0300
It seems like he doesn't get all the exercises in the Data base, It can't use the "For" loop
2.When i try the rest of the programs within the list, I get 404 error -
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/programs/2/
Raised by: program.views.ProgramDetailView
No exercise found matching the query
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
In the SQLite, I do have exercises related to "pk=2" so I am assuming that it at list show me the same error has "pk=1" but it seems like he cant find the exercises in the data base.
Appreciates your help.
Thanks, and I hope I didn't miss any "Code lines".

How to Increment Next Record in Django / Templates

In index.html - I am able to read the first item of my table / model in Django just fine with my code below. However, after the user clicks the next button - I want it to retrieve the next item of my table / model. (how / where do I build this counter?)
here is views.py
def index(request):
flash_dict = {'flashcards': Card.objects.get(pk=1)}
return render(request, 'flash/index.html', context=flash_dict)
here is index.html
<div class = "jumbotron">
{% if flashcards %}
<p class = 'question'>{{ flashcards }}</p>
<p class = 'answer'>{{ flashcards.flash_answer }}</p>
<button type="button" class="btn btn-primary" onclick = "flip()">Flip</button>
<button type="button" class="btn btn-primary">Next</button>
{% else %}
<p>NO ACCESS RECORDS FOUND!</p>
{% endif %}
</div>
here is models.py
from django.db import models
# Create your models here.
class Card(models.Model):
flash_question = models.TextField()
flash_answer = models.TextField()
objects = models.Manager()
def __str__(self):
return self.flash_question
here is urls.py (under base project folder)
from django.contrib import admin
from django.urls import path, include
from flash import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name='index'),
]
here is urls.py (under app folder)
from django.conf.urls import url
from flash import views
urlpatterns = [
url(r'^$', views.index, name='index')
]
The semantically 'correct' way to make this work is by rewiring your code significantly:
First, you need to modify urls.py, in your base folder, so that the flashcard URL takes a flashcard ID. This will allow you to visit flashcard/1/, flashcard/2/, etc. and see data for the corresponding flashcard.
urls.py
from django.contrib import admin
from django.urls import path, include
from flash import views
urlpatterns = [
path('admin/', admin.site.urls),
path('flashcard/<int:card>/',views.index,name='flashcard'), # Here we are adding a variable to the URL pattern, which will be passed to the view
]
Next, you need to modify your view so that it takes a flashcard ID from the URL and renders the flashcard in question:
views.py
def flashcard(request, card=1): # Your view will now look for the 'card' variable in your URL pattern.
flash_dict = {'flashcards': Card.objects.get(pk=card)} # Your 'flashcards' variable now holds the card that corresponds to the ID in the URL
return render(request, 'flash/index.html', context=flash_dict)
Then, we'll write a method within your Card model that will pull the next card when self.get_next is called. Now, if you have a Card object, you can find the next card by calling card.get_next():
models.py
from django.db import models
# Create your models here.
class Card(models.Model):
flash_question = models.TextField()
flash_answer = models.TextField()
objects = models.Manager()
def __str__(self):
return self.flash_question
def get_next(self):
next = Card.objects.filter(id__gt=self.id).order_by('id').first()
if next:
return next
# If the current card is the last one, return the first card in the deck
else:
return Card.objects.all().order_by('id').first()
Finally, we'll replace the buttons in your template with an a href that links to the new 'flashcard' view, and passes it the ID of the next card in the sequence:
template.html
<div class = "jumbotron">
{% if flashcards %}
<p class = 'question'>{{ flashcards }}</p>
<p class = 'answer'>{{ flashcards.flash_answer }}</p>
<!-- Here we link to the 'flashcard' view, and pass it the ID of the next card in the sequence -->
Next flashcard
{% else %}
<p>NO ACCESS RECORDS FOUND!</p>
{% endif %}
</div>
Now, try visiting /flashcard/1 to see how everything works together.

Django - No Reverse Match Error - URL only works with static values

I'm working on a Django site that displays a list of projects. You go to a page, you see a project, you click it, and you can then see project details and have the option to edit the page.
For each individual project, I use a template called project.html. Then on that page, I have a link to edit_project.html
Edit Project
Whenever I try to load the project page to view, I get this error:
Reverse for 'edit_project' with arguments '('',)' not found. 1
pattern(s) tried: ['edit_project/(?P\d+)/$']
I checked the urls, and they seemed fine. So, I tried hard-coding a project id that I knew was in the database. For example, I called:
Edit Project
instead of calling that same thing with "project.id". When I did that, the error went away.
Why does this work with a hard-coded value instead of a project.id variable?
I also tried deleting the database and all the migrations in case something strange was happening there. I got the same issue though.
Here is the code I used to set everything up in case it is helpful.
project.html
{% extends "profile/base.html" %}
{% block content %}
<p>
Edit Project
</p>
<p>Status: {{ status }}</p>
{% endblock content %}
edit_project.html
{% block content %}
<p>{{ project }}</p>
<p>Edit project:</p>
<form action="{% url 'profile:edit_project' project.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save Changes</button>
</form>
{% endblock content %}
views.py
#login_required
def edit_project(request, project_id):
"""Edit an existing project"""
project = Project.objects.get(id=project_id)
#Make sure the project belongs to the owner
if project.owner != request.user:
return Http404
if request.method != 'POST':
#Initial request; pre-fill form with the current entry
form = ProjectForm(instance=project)
else:
#POST data submitted; process data
form = ProjectForm(instance=project, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('profile:project',args=[project.id]))
context = {'project':project, 'form':form}
return render(render, 'profile/edit_project.html', context)
(project) forms.py
class DateInput(forms.DateTimeInput):
input_type = 'date'
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['name','description','status', 'project_type', 'start_date','end_date', 'due_date']
labels = {'name':'Name', 'description':'Description:', 'status':'Status', 'project_type':'Project Type',
'start_date':'Start Date', 'end_date':'End Date', 'due_date': 'Due Date',}
widgets ={'description':forms.Textarea(attrs={'cols':80}),'start_date':DateInput(),
'end_date':DateInput(),'due_date':DateInput()}
urls.py
urlpatterns = [
#Home page
url('^$', views.index, name='index'),
#Show all projects
url('projects/$', views.projects, name='projects'),
#Details for single project
url('^projects/(?P<project_id>\d+)/$', views.project, name='project'),
#Page for editing a single project
url('^edit_project/(?P<project_id>\d+)/$', views.edit_project, name='edit_project'),
]

django getting error about views.py

This is my views.py
from django.shortcuts import render
from . models import Houses
def houses_list(request):
house = Houses.objects.all().order_by('owner')
return render('Houses.html',{'houses':house})
this my models.py
from django.db import models
class Houses(models.Model):
owner = models.CharField(max_length=250)
house_name = models.CharField(max_length=500)
country = models.CharField(max_length=500)
genre = models.CharField(max_length=100)
def __str__(self):
return self.house_name
class house(models.Model):
houses = models.ForeignKey(Houses, on_delete=models.CASCADE)
file_type = models.CharField(max_length=10)
house_title = models.CharField(max_length=250)
this my url.py
from django.urls import path
from . import views
urlpatterns= [
path('', views.Houses, name='Houses'),
]
this my html file
{% load static %}
<html>
<head>
<meta charset = "utf-8">
<title>Houses</title>
</head>
<body>
<h1>House list</h1>
<div class="house">
{% for house in houses %}
<div class="house">
<h2>{{Houses.house_name}}</h2>
<p>{{Houses.owner}}</p>
<p>{{Houses.genre}}</p>
</div>
{% endfor %}
</div>
</body>
</html>
I'm tring to get the data from my database but on the web getting attribute no object error.But I can see the all objects on the admin page do you have any idea what I'm doing wrong?
Here is code with fixed bugs:
The bug in urls was causing AttributeError. Fix code to:
urlpatterns= [
path('', views.houses_list, name='Houses'),
]
Remember that urls must point to views. But after you fix this, the next error will be in the views.py, because render() is missing request argument. Change to:
def houses_list(request):
house = Houses.objects.all().order_by('owner')
return render(request, 'Houses.html',{'houses':house})
The bug in the template would just render empty. Fix to:
{% for house in houses %}
<div class="house">
<h2>{{house.house_name}}</h2>
<p>{{house.owner}}</p>
<p>{{house.genre}}</p>
</div>
{% endfor %}
You are trying to get attributes from the Houses class in your template. Replace Houses with house, which is the current Houses object returned by the for loop. `
<h1>House list</h1>
<div class="house">
{% for house in houses %}
<div class="house">
<h2>{{house.house_name}}</h2>
<p>{{house.owner}}</p>
<p>{{house.genre}}</p>
</div>
{% endfor %}
</div>
EDIT
As Borut mentioned, your render call in houses_list is missing the request, i.e.
return render(request, ...)
Also, your urlpatterns is referencing Houses model instead of the houses_list view, i.e. it should be views.houses_list instead of views.Houses.

Adding a custom placeholder to django-cms

I'm trying to create a custom placeholder to add an admin-editable section on a website. Django-cms' documentation is really generic about what's to be done to add it.
The placeholder lives in a separate app, called contacts, already added to the settings.py file
Here's my code up to now (skipping imports to be less verbose):
models.py
class ContactsPlaceholder(models.Model):
phone = models.CharField(max_length=100)
email = models.CharField(max_length=100)
address = models.TextField(max_length=700)
# your fields
my_placeholder = PlaceholderField('contacts_contactsplaceholder')
# your methods
def __unicode__(self):
return "Contacts Placeholder"
views.py
def contacts(request):
# Load the the contacts from db
contactsfields = ContactsField.objects.all()
contacts_placeholder = ContactsPlaceholder.objects.all()
context = {"contactsfields" : contactsfields, "contacts_placeholder" : contacts_placeholder}
return render(request, "../templates/contacts.html", context)
def contacts_placeholder_detail(request, id): # is this really useful?
object = get_object_or_404(ContactsPlaceholder, id=id)
return render_to_response('../templates/contacts_placeholder_detail.html', {
'object': object,
}, context_instance=RequestContext(request))
contacts.html
{% extends "base.html" %}
{% load cms_tags %}
{% block content %}
<div>
<h1>Contacts</h1>
{% placeholder "contacts_placeholder" or %}
<p>Placeholder is empty</p>
{% endplaceholder %}
</div>
{% endblock content %}
and finally, admin.py
class ContactsPlaceholderAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
# Editable fields
frontend_editable_fields = ("phone", "email", "address")
# Form fields order and sections
fieldsets = [
(None,{"fields" : ["phone", "email", "address"]})
]
admin.site.register(ContactsPlaceholder, ContactsPlaceholderAdmin)
With this configuration, after having run python manage.py syncdb I do get "Placeholder is empty" in the html response, and of course the placeholder is not editable using the standard frontend editor, which was the desired behaviour.
Going to 127.0.0.1:8000/admin/ i can see the "Contacts Placeholder" table, however when I click it or try to add items I do get the following error:
OperationalError at /us/admin/contacts/contactsplaceholder/
no such column: contacts_contactsplaceholder.phone
If the contacts() view is rendered via an app hook then using {% placeholder "contacts_placeholder" %} in the template won't work.
When using Placeholders in apps connected to the CMS via an AppHook you must use {% static_placeholder "MyPlaceholder" %} instead of the usual {% Placeholder "MyPlaceholder" %}
If you've got an app or a plugin in which you've created a PlaceholderField, then in your template which renders that, you'd need the following tag;
{% render_placeholder instance.placeholderfieldname %}

Categories