Load Django Objects Quicker - python

so I'm working on a Django news aggregator project. A main aspect of the project involves me fetching reddit and twitter posts through their respective APIs, saving the post data to a post model, then loading those model objects onto the page.
This is what I would prefer to do over fetching the data and displaying it directly through the response objects.
Right now, I have two separate timelines of reddit posts, and twitters posts, adjacent to each other on the page. Last time I loaded the page, it took a really long time. This is what the page looks like btw:
I was hoping someone could explain to me how I can get my page to load faster, and also how to integrate timeline/newsfeed functionality well. Lets say I have over 1500 post objects in my database, I don't want to load all 1500 on the page at one time. I'd like to load like the first 100, then if someone scrolls down the page enough, the next 100 become loaded, etc. Is there an easy/efficient way to go about this?
Thanks
EDIT 6/30/21
Here is my code:
views.py
from .models import Post
from news import services
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
def mainpage(request):
all_posts=Post.objects.all()
context={'posts': all_posts}
return render(request, "mainpage.html", context)
models.py
from django.db import models
class Post(models.Model):
# Reddit, Twitter, Youtube
post_type = models.CharField(
max_length=20, null=True, blank=True)
root_url = models.CharField(max_length=200, default="")
html = models.TextField(default="")
created_at = models.DateTimeField(auto_now_add=True)
template
{% extends 'base.html' %} {% block content %} {% autoescape off %} {% load red_attempt %} {% load tweet_tags %}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
<div class="container">
<div class="row">
<div class="col-6">
<h3 class='text-center'>Twitter News</h3>
{% for post in posts %}
{% if post.post_type == 'Twitter' %}
<div class="mdl-card__media" id="timeline"></div>
{{ post.html }}
{% endif %}
<br>
{% endfor %}
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="col-6">
<h3 class='text-center'>Reddit News</h3>
{% for post in posts %}
{% if post.post_type == 'Reddit' %}
<div class="mdl-card__media" id="timeline"></div>
{{ post.html }}
{% endif %}
<br>
{% endfor %}
<script async src="//embed.redditmedia.com/widgets/platform.js" charset="UTF-8"></script>
</div>
</div>
</div>
{% endautoescape %}{% endblock %}
<script async src="//embed.redditmedia.com/widgets/platform.js" charset="UTF-8"></script>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>

Related

Django template isn't displaying some model object attributes on the page but will display others

I'm following a tutorial on Real Python to create a very simple portfolio website.
https://realpython.com/get-started-with-django-1/
I've created a Project model:
from django.db import models
class Project(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
technology = models.CharField(max_length=20)
image = models.FilePathField(path="/img")
I've added a number of different objects/projects to this model in the shell and saved them. Here is the HTML for the web page I'm displaying them on:
{% extends "base.html" %}
{% load static %}
{% block page_content %}
<h1>Projects</h1>
<div class="row">
{% for project in projects %}
<div class="col-md-4">
<div class="card mb-2">
<img class="card-img-top" src="{% static project.image %}">
<div class="card-body">
<h5 class="card-title">{{ project.title }}</h5>
<p class="card-text">{{ project.description }}</p>
<a href="{% url 'project_detail' project.pk %}" class="btn-primary">
Read More
</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
As you can see, I'm displaying them on cards that are added using a for loop that iterates every time a new object is created. On this page, the project title, description and read more button are displaying correctly but for some reason the image is not. I have the images placed in a /static/img folder in the same directory as the app 'projects'. And I've tried re-entering the object data, using PNGs, JPEGs etc. but none of these seem to get the images to display correctly.
Next, the 'in detail' page is loaded when the read more button is clicked. Here is the HTML for that:
{% extends "base.html" %}
{% load static %}
{% block page_content %}
<h1>{{ project.title }}</h1>
<div class="row">
<div class="col-md-8">
<img src="{% static project.image %}" alt="" width="100%">
</div>
<div class="col-md-4">
<h5>About the project:</h5>
<p>{{ project.description }}</p>
<br>
<h5>Technology used:</h5>
<p>{{ project.technology }}</p>
</div>
</div>
{% endblock %}
On this page, not only does the image not load, but the project title, description and technology used don't display either. Only a blank space where the image should be and the h5 text shown above is displayed.
I've been following the tutorial as exact as I can and only making small aesthetic changes here and there. I've been through the source code on github and compared my code directly to the authors code and the core components all seem to be exactly the same. Am I missing something?
ADDITIONAL INFO
settings.py static files:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = 'static/img/'
views.py for the 'projects' app:
from django.shortcuts import render
from projects.models import Project
def project_index(request):
projects = Project.objects.all()
context = {
'projects': projects
}
return render(request, 'project_index.html', context)
def project_detail(request, pk):
projects = Project.objects.get(pk=pk)
context = {
'projects': projects
}
return render(request, 'project_detail.html', context)

Understanting Django inheritance templates

Im really lost about this, im trying to understand a django inheritance template about
I have a layout with a navbar and html structure:
todos/templates/todos/layout.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<title>Practice Django</title>
</head>
<body>
<nav class="navbar navbar-dark bg-dark justify-content-between">
<div>
<a class="navbar-brand" href="/">Django app</a>
Page 1
Page 2
</div>
<form action="" class="form-inline">
<input
type="search"
placeholder="Search Todo"
aria-label="Search"
class="form-control mr-sm-2"
/>
<button type="submit" class="btn btn-outline-success my-2 my-sm-0">
Search
</button>
</form>
</nav>
<div class="container">
{% block content %} {% endblock %}
</div>
</body>
</html>
then im trying to setup a index page with a grid, a column for show todos and the another one for create a new todo.
todos/templates/todos/base.html
{% block content %}
<h1 class="text-center">Base Page</h1>
<div class="row">
<div class="col">
{% block todolist %}
{% include 'todos/todos_list.html' %}
{% endblock %}
</div>
<div class="col">
{% block addtodo %}
{% include 'todos/add_todo.html' %}
{% endblock %}
</div>
</div>
{% endblock %}
todos/templates/todos/add_todo.html
{% extends 'todos/base.html' %}
{% block addtodo %}
<h3 class="text-center">subpage addtodo</h3>
{% endblock %}
todos/templates/todos/todos_list.html
{% extends 'todos/base.html' %}
{% block todolist %}
<h3 class="text-center">subpage todolist</h3>
{% endblock %}
For try to understand it, i made a same classes for both views, todo_list and add_todo from different class sources.
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import loader
from django.views.generic import ListView, DetailView
from .models import Todo
class TodoList(ListView):
template_name = 'todos/todos_list.html'
context_object_name= 'todos'
# Lo que devuelve esta funcion se añade al context object name
def get_queryset(self):
return Todo.objects.all()
class AddTodo(ListView):
template_name = 'todos/add_todo.html'
context_object_name= 'todos'
# Lo que devuelve esta funcion se añade al context object name
def get_queryset(self):
return Todo.objects.all()
My urls.py i guess, to show both classes in index pages, the same route url
from django.urls import path
from . import views
urlpatterns = [
path('', views.TodoList.as_view(), name='todolist'),
path('', views.AddTodo.as_view(), name='addtodo')
]
But this does not work, with this error:
RecursionError at /
maximum recursion depth exceeded while calling a Python object
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 3.1.1
Exception Type: RecursionError
Exception Value:
maximum recursion depth exceeded while calling a Python object
Exception Location: /home/adrian/.local/lib/python3.8/site-packages/django/utils/functional.py, line 241, in inner
Python Executable: /usr/bin/python3
Python Version: 3.8.2
Python Path:
['/home/adrian/code/python/practice',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/home/adrian/.local/lib/python3.8/site-packages',
'/usr/local/lib/python3.8/dist-packages',
'/usr/lib/python3/dist-packages']
Server time: Thu, 24 Sep 2020 16:43:24 +0000
I was thinking to make both operations (show todo list and add a new todo form) with the same class, but i dont know how do it that properly, the object its show a both classes, templates in the same route, in this case in root /.
Any clues about? thanks in advance
You should not use {% include %}, since then you end up with infinite recursion. You can for example make a base:
{% block content %}
<h1 class="text-center">Base Page</h1>
<div class="row">
<div class="col">
{% block items %}
{% endblock %}
</div>
<div class="col">
{% block otheritems %}
{% endblock %}
</div>
</div>
{% endblock %}
If you later use {% extend … %} [Django-doc], it means you take the entire template of the one your refer to, but for the blocks you specify and the "child template", you render another value. So your child can look for example as:
{% extends 'todos/base.html' %}
{% block items %}
<h3 class="text-center">subpage addtodo</h3>
{% endblock %}
{% extends 'todos/base.html' %}
{% block items %}
<h3 class="text-center">subpage todolist</h3>
{% endblock %}
Here you will thus render the <h1 class=""> part in the child templates. The only thing that will differ is that the part in the block {% block items %} … {% endblock %} by the content you provide.
Here it however looks like you want two views to provide content for the same page. That is not how it works. A view is the logic that maps a request to a response. A view does not per se renders a template, nor does it only renders maximum one template. A view can render as much templates as you want.
If you thus want a single page with two items to fill in, you make a view, that renders for example a template that fills in the two blocks. So we thus define a single URL pattern for this path:
from django.urls import path
from . import views
urlpatterns = [
path('', views.TodoList.as_view(), name='add_todo'),
]
and in the view, we allow one to also access the list of todos:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import loader
from django.views.generic import ListView, DetailView
from .models import Todo
class TodoList(CreateVieww):
template_name = 'todos/todos_list.html'
model = Todo
fields = '__all__'
def todos(self):
return Todo.objects.all()
in the template, we finally fill in two blocks: one with the Todos, and one with the form:
{% extends 'todos/base.html' %}
{% block items %}
{% for todo in view.todos %}
{{ todo }}
{% endfor %}
{% endblock %}
{% block otheritems %}
<form method="post" action="{% url 'add_todo' %}">
{{ form }}
</form>
{% endblock %}

Django template language extends doesn't work

Hi guys I am studying django framework using "django by example" book. The problem I am facing is that the template language does not work even I copy and pasted source code from book and/or github.
A blog application that has post model and is inside the mysite project.
You can see the code in picture and the result too:
Inside blog\templates\blog .
blog\templates\blog\base.html
<!-- its base.html -->
{% load staticfiles %}
<!DOCTYPE HTML>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>My blog</h2>
<p>This is my blog.</p>
</div>
</body>
</html>
Its the list that extends base.html and located in blog\template\blog\post:
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
Here is views.py
from django.shortcuts import render, get_list_or_404
from .models import Post
def post_list(request):
posts=Post.published.all()
return render(request,'blog/post/list.html',{'posts':posts})
def post_detail(request, year, month, day, post):
post=get_list_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
return render(request,'blog/post/detail.html',
{'post':post})

Django variable not visible in header section

I have a basic start to a blog, it lists out blog articles from the database in post_list.html that extends from header.html. I am trying also to get a variable in the header as a slogan but this is not working.
header.html - this renders without the "propaganda.slogan" which is entered from the admin pages and has content:
<!DOCTYPE html>
<html lang="en">
<head>
<title>hey!</title>
<meta charset="utf-8" />
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'blog/css/bulma.css' %}" type="text/css"/>
</head>
<body>
<section class="hero is-success is-bold">
<div class="hero-body">
<div class="container">
{% block slogan %}
<ul>
{% for propaganda in propagandas %}
<li>{{ propaganda.slogan }}</li>
{% endfor %}
</ul>
{% endblock %}
<h1 class="title">
My weblog
</h1>
</div>
</div>
</section>
{% block content %}
{% endblock %}
</body>
</html>
post_list.html extends header.html and displays a list of posts from models.py:
{% extends "blog/header.html" %}
{% block content %}
{% for post in posts %}
<section class="section">
<div class="container">
<h1 class="title">{{ post.title }}</h1>
<p>{{ post.summary|linebreaksbr }}</p>
<p>published: {{ post.last_edited }}</p>
</div>
</section>
{% endfor %}
{% endblock %}
models.py looks like this:
from django.db import models
from django.utils import timezone
# Create your models here.
class Propaganda(models.Model):
slogan = models.CharField(max_length=140, blank=True, null=True)
def __str__(self):
return self.slogan
class Post(models.Model):
title = models.CharField(max_length=140, blank=False, null=False)
content = models.TextField()
summary = models.CharField(max_length=500)
created_date = models.DateTimeField()
last_edited = models.DateTimeField()
def __str__(self):
return self.title
finally, views.py is:
from django.shortcuts import render
from .models import Post, Propaganda
# Create your views here.
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
def header(request):
propagandas = Propaganda.objects.all()
return render(request, 'blog/header.html', {'propagandas': propagandas})
So why can I get the list of post titles, summary and date in the post_list.html but I can't get a list of propagandist slogans in the header?
to me it looks like the same code, almost?
I get no error from the dev server or in the browser :(
You'll need to pass the list of propagnadas to the context of the current template; including a template has little or nothing to do with the associated (if this makes any sense in the first place) view of the included template:
def post_list(request):
posts = Post.objects.all()
propagandas = Propaganda.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts, 'propagandas': propagandas})

Django floppyforms OSMPointWidget does not display a map

I am trying to put an OSM-map, similar to the one in the geodjango-admin, into a form on my main site.
I decided to use floppyforms, set everything up like in the documentation and it seems to get recognized, but strangely the map does not appear. Firebug shows that there is just an empty <div id="id_coord_map"></div> instead of the map, but it has all the right dimensions. The debug-textbox and the "Delete all features"-link are there like they should be. But, when I open the site, Firebug does not show any javascript requests in the 'network'-tab, so maybe that is a hint.
I guess I missed something or something isn't correctly included, but I tried for hours and really don't know anymore. Amongst other things I set all the paths for static files and run manage.py collectstatic, I also tried to not use the generic edit views, but it came out the same.
Here are the relevant parts in the code:
#views.py
import floppyforms as forms
...
class OSMPointWidget(forms.gis.PointWidget, forms.gis.BaseOsmWidget):
pass
class LocationCreateView(CreateView):
model = Location
fields = ['name', 'zip', 'coord']
form_class = modelform_factory(Location,
widgets={"coord": forms.gis.PointWidget(attrs = {
'display_wkt': True,
'map_srid': 4326,
'map_width': 700,
'map_height': 500,})})
#models.py
class Location(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=255, blank=True, default='', unique=True)
coord = models.PointField()
zip = models.CharField(max_length=5, default='12345')
objects = models.GeoManager()
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super(Location, self).save(*args, **kwargs)
#urls.py
urlpatterns = patterns('',
...
url(r"location/$", views.LocationCreateView.as_view(),
name = "locationcreate"),
...
)
#location_form.html
{% extends "_layouts/base.html" %}
{% block page_title %}Enter Location | {% endblock %}
{% block page_content %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
#base.html
<!doctype html>
<html>
<head>
<title>{% block page_title %}{% endblock %}Calendar</title>
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.css">
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap-theme.css" >
</head>
<body>
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<h1>EVENTCALENDAR</h1>
</div>
<div class="container">
{% block page_content %}{% endblock %}
</div>
</div>
</body>
</html>
I just had a similar issue and realised that I needed to include a {{ form.media }} tag in the header and then django-floppyforms supplies the relevant javascript files to make the map magically appear.
Somewhere in the head of base.html include a block for extra javascript
{% block extra_js %}{% endblock %}
Then fill in the block in your location_form.html
{% block extra_js %}
{{ form.media }}
{% endblock %}

Categories