Calling Model method inside template file - python

I am learning to create a blog website using django. I encountered an issue while calling my model method inside template file. The site is not displaying contents inside the body. It was working fine when i used article.body but its not working when i use article.snippet.
models.py file:-
...
from django.db import models
class Article(models.Model):
title = models.CharField(max_length = 100)
slug = models.SlugField()
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def snippet(self):
return self.body[:50]
...
articles_list.html file:-
...
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Articles</title>
</head>
<body>
<h1>Articles List</h1>
<div class="articles">
{% for article in articles %}
<div class="article">
<h2>{{article.title}}</h2>
<p>{{article.body.snippet}}</p>
<p>{{article.date}}</p>
</div>
{% endfor %}
</div>
</body>
</html>
...
views.py file:-
...
from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
def articles_list(request):
articles = Article.objects.all()
return render(request, 'articles/articles_list.html', {'articles': articles})
...
There is no error displayed in code but still there is no output inside body tag.

You can make use of a built-in Slice filter in your template
like this
<p<{{ article.body|slice:":50" }}</p>
But for some reason, if you want to call any model methods from the templates you can use #property decorator to access it.
like this
class Article(models.Model):
...
#property
def snippet(self):
return self.body[:50]

You can just call
<p>{{article.snippet}}</p>
instead of:
<p>{{article.body.snippet}}</p>
because snippet is a method in the same model so you can call it directly, and body is not a ForeignKey

Related

Django: how to create a dictionary of objects and display in templates

Hey I have had a look at similar questions but none really relate to what I am trying to do, they either explain how to order things in the admin panel or simply iterating over object dictionaries.
I have created a basic photo model that contains a value gallery_order so I can edit them in Admin.
I wish to populate my template with the pictures according to the gallery_order values in order from 1 upward.
I guess the best way to handle it is with a dictionary but I do not know where to initialize it, if I put it in the picture model then each picture holds a dict with all the pictures order number and url in it which seems mental.
My current model:
class Picture(models.Model):
title = models.CharField(max_length=36, blank=False, unique=True)
gallery_order = models.IntegerField(default=0)
image = models.ImageField(upload_to='photos/', blank=False)
def __str__(self):
return self.title
My template code:
<head>
<meta charset="utf-8">
{% block content %}
<div class="row">
{% if pictures %}
{% for picture in pictures %}
<div class="col-md-12">
<div class="card mb-0">
<img class="card-img-top" src="{{ picture.image.url }}">
</div>
</div>
{% endfor %}
{% endif %}
</div>
{% endblock content %}
</head>
my admin code:
#admin.register(Picture)
class PictureAdmin(admin.ModelAdmin):
list_display = ('gallery_order', 'title', 'image')
list_display_links = ['gallery_order']
search_fields = ['title']
def get_queryset(self, request):
queryset = super(PictureAdmin, self).get_queryset(request)
queryset = queryset.order_by('gallery_order')
return queryset
I tried to figure out how django was displaying them by looking at the PK in psotgres db but it seems to simply display them according to last edited.
Thank You :)
You could also do this at the model level by adding the following at the end of your model.
class Meta:
ordering = ['gallery_order']
I am so silly sometimes I forgot about my views!
all I had to do was specify order_by for goodness sake...
class Home(View):
pictures = Picture.objects.all().order_by('gallery_order')
def get(self, request):
return render(request, 'home.html', {'pictures': self.pictures})

From Python function to Django template

I'm trying to get my head around Django and understand how I can show results of Python functions in Django's templates. As a simple example, let's say I have a model with a list of questions and I want to use a function to return the number of questions and for this result to be shown in a template. How can I do it?
I tried to do it below but it doesn't work!
Thanks in advance
models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
views.py
from django.shortcuts import render
from django_app import models
from django.views.generic import ListView
from django_app.models import Question
class TestListView(ListView):
model = Question
context_object_name = 'test_details'
def Test(self):
return Question.objects.count()
urls.py
from django.urls import path
from django_app import views
from django_app.views import TestListView
app_name = 'django_app'
urlpatterns = [
path('',TestListView.as_view(), name='Test'),
]
question_list.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% for item in test_details %}
{{Test}}
{{item.question_text}}
{% endfor %}
</body>
</html>
You can override the get_context_data method of your view to add extra variable into your context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['Test'] = Question.objects.count()
return context
You can also get the count of the questions without having to alter the context. You can get it from the queryset
{{ test_details.count }}

Django form image choice- widget type

Ok. I want to make an app that is changing image from model A and save it as new to model B. On the form in template I want visible images to choose. How can I do it?
Model and form A
model
from django.db import models
class Photo(models.Model):
photo = models.ImageField(blank=True, null=True)
form
from django import forms
from .models import Photo
class Photoform(forms.ModelForm):
photo = forms.ImageField(required=True)
class Meta:
model = Photo
fields = ('photo',)
Model and form B
model
from django.db import models
class Meme(models.Model):
meme = models.ImageField(blank=True, null=True)
form
from django import forms
from Uploader.models import Photo
class Memeform(forms.Form):
meme = forms.ModelChoiceField(Photo.objects.all(), widget=forms.RadioSelect)
class Meta:
model = Photo
fields = ('meme',)
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method= "post" enctype="multipart/form-data">
<p>
<h2>Your image here</h2>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Create</button>
</p>
</form>
</body>
</html>
Now i have widget RadioSelect, but i need to be images visible to choose.
form.fields["photo"].queryset = Photo.objects.all() in your views..You can refer more from here..http://www.wkoorts.com/wkblog/2009/08/10/pre-populate-django-modelform-with-specific-queryset/
in your views
form.fields["photo"].queryset = Photo.objects.all()
You can refer more from.
And in HTML you should write down:
{% csrf_token %}
{{ form.media }}

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.

Django-tables2: ValueError at /interactive_table/ Expected table or queryset, not str

I was following along with the tutorial for Django-tables2 tutorial (which can be found here: https://django-tables2.readthedocs.io/en/latest/pages/tutorial.html). I've fixed all the errors up until now, but I've hit one that I cannot solve. It says that my code expected a table or queryset, not a string.
I've looked around, and all the solutions to this problem all blame the version being out of date, but I have updated it and I still get this error.
Does anybody know what I'm doing wrong?
Here is my views.py:
from django.shortcuts import render
from interactive_table import models
def people(request):
return render(request, 'template.html', {'obj': models.people.objects.all()})
Here is my models.py:
from django.db import models
class people(models.Model):
name = models.CharField(max_length = 40, verbose_name = 'Full Name')
Here is my template.html:
{# tutorial/templates/people.html #}
{% load render_table from django_tables2 %}
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="{{ STATIC_URL }}django_tables2/themes/paleblue/css/screen.css" />
</head>
<body>
{% render_table people %}
</body>
</html>
change obj to people in render function.
Try to understand how templates and template variables work with django.
Documentations might be a good place to look
Change your template response to return people instead of obj
return render(request, 'template.html', {'people': models.people.objects.all()})

Categories