Image Failure in Django Blog - python

I've created a simple django blog, and I'm having trouble getting images to consistently show up in my posts. Specifically, my images appear in the "list" view (the home page for the site), but not in the "detail" view (when viewing one individual post). The website is here if you want to see the issue live: endicott.co
The code for the list view is below:
{% extends "blog/base.html" %}
{% block title %}endicott.co{% endblock %}
{% block content %}
<div class="page-header">
<h1>endicott.co</h1>
<p>Perspectives on society, data, and economics</p>
</div>
{% 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>
<img src="{{ post.image.url }}" alt="img">
{{ post.body|linebreaks }}
{% endfor %}
{% include "pagination.html" with page=page_obj %}
{% endblock %}
The code for the detail view is listed below:
{% extends "blog/base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<img src="{{ post.image.url }}" alt="img">
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
{% endblock %}
Any thoughts on why django is correctly showing the image in the list but not the detail view? Let me know if I should post any additional code for more background.
The file structure is as follows:
blog/
-__pycache__/
-migrations/
-templates/
--blog/
---post/
----detail.html
----list.html
---base.html
--pagination.html
-__init__.py
-admin.py
-apps.py
-models.py
-tests.py
-urls.py
-view.py
media/
-img/
--[where images are stored]
mysite/
-__pycache__/
-static/
-__init__.py
-settings.py
-urls.py
-wsgi.py
My blog urls.py file is below:
from django.conf.urls import url
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# post views
#url(r'^$', views.post_list, name='post_list'),
url(r'^$', views.PostListView.as_view(), name='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/'\
r'(?P<post>[-\w]+)/$',
views.post_detail,
name='post_detail'),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The mysite urls.py file is below:
from django.conf.urls import include, url
from django.contrib import admin
##### adds
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('blog.urls',
namespace='blog',
app_name='blog')),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Your problem is that the src= is understood as a relative URL (just like saq7 pointed). You want the image to have its src= pointing to an absolute URL (starting with http://) since the image sits at an absolute location from the website root (from the domain).
To perform that, you shall use {% media post.image.url %}. Note that for that you need to perform a couple of additions to settings.py, notably MEDIA_ROOT and MEDIA_URL, in order for the {% media %} template tag to work.
Using media files in this fashion (with {% media %}) is the most common and accepted way. Note that in production (i.e. behind a real webserver) such files shall not be server by Django, note how that article has:
This is not suitable for production use!
Yet, there is another article in the Django documentation explaining what to do to configure your webserver to serve these files.
Also, if you set MEDIA_URL = '/media/' you will need to remove the media/ prefix from post.image.url.

Related

Django - Incorporating new models with their own pages

I have managed to set up one model within my Django project and can create posts within it and display those posts through views and templates, however, I don't appear to be able to do the same with the new Models I've created. I have attempted to do this as I have done with the initial Model, which is to set up its own html files, just as the first one, as well as similar entries in urls.py in the main project folder and views.py in the app folder.
Edit for more context: Basically, the Article model has been set up with the templates article_detail.html and article_list.html and all of the entries within that model are pulled from the Admin app and are viewable. I have created another model, Offensive, and would also like to do the same as with the Article entries, so I attempted to copy what I had done and made the Offensive model it's own templates (offensive_detail.html and offensive_list.html:).
This does not appear to have worked, however. Creating a link for Offensive on base_template.html does not go anywhere, it just stays on the same page. Does not re-direct to the offensive details page that will show the list of offensive articles.
My intent is to have different categories aligned with different models and have all of those categories and corresponding pages as links within a navbar.
I'm not entirely sure where I'm going wrong, or even if I'm anywhere near right.
Help would be very much appreciated.
Here is the folder structure of my project
Files under the app folder:
article_detail.html:
{% extends 'base_layout.html' %}
{% block content %}
<div class="article-detail">
<div class="article">
<h2>{{ article.title }}</h2>
<p>{{ article.body }}</p>
<p>{{ article.date }}</p>
</div>
</div>
{% endblock %}
article_list.html:
{% extends 'base_layout.html' %}
{% block content %}
<h1>Articles List</h1>
<div class="articles">
{% for article in articles %}
<div class="article">
<h2>{{ article.title }}</h2>
<p>{{ article.date }}</p>
</div>
{% endfor %}
</div>
</body>
{% endblock %}
offensive_detail.html:
{% extends 'base_layout.html' %}
{% block content %}
<div class="offensive_articles">
<div class="offensive_list">
<h2>{{ offensive_article.title }}</h2>
<p>{{ offensive_article.body }}</p>
<p>{{ offensive_article.date }}</p>
</div>
</div>
{% endblock %}
offensive_list.html:
{% extends 'base_layout.html' %}
{% block content %}
<h1>Offensive Articles List</h1>
<div class="offensive_articles">
{% for offensive_article in offensive_articles %}
<div class="offensive_article">
<h2>{{ offensive_article.title }}</h2>
<p>{{ offensive_article.date }}</p>
</div>
{% endfor %}
</div>
</body>
{% endblock %}
models.py:
from django.db import models
from PIL import Image
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField() # URL of post
body = models.TextField()
date = models.DateTimeField(auto_now_add=True) # auto populate with the current time
thumb = models.ImageField(default='default.jpg', blank=True)
# add in author
def __str__(self):
return self.title
class Offensive(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField() # URL of post
body = models.TextField()
date = models.DateTimeField(auto_now_add=True) # auto populate with the current time
thumb = models.ImageField(default='default.jpg', blank=True)
def __str__(self):
return self.title
urls.py:
from django.urls import path
from django.conf.urls import url
from . import views
app_name = 'articles'
urlpatterns = [
url(r'^$', views.article_list, name="list"),
url(r'^$', views.offensive_list, name="offensive_list"),
url(r"^(?P<slug>[\w-]+)/$", views.article_detail, name="detail"),
url(r"^(?P<slug>[\w-]+)/$", views.offensive_detail, name="offensive_detail"),
]
views.py:
from django.http import HttpResponse
from django.shortcuts import render
from .models import Article, Offensive, Defensive, Fitness, Coding
def article_list(request):
articles = Article.objects.all().order_by('date')
return render(request, 'articles/article_list.html', {'articles': articles})
def about(request):
#return HttpResponse('about')
return render(request, 'about.html')
def article_detail(request, slug):
#return HttpResponse(slug)
article = Article.objects.get(slug=slug)
return render(request, 'articles/article_detail.html', { 'article':article })
def offensive_list(request):
offensive_articles = Offensive.objects.all().order_by('date')
return render(request, 'articles/offensive_list.html', { 'offensive_article': offensive_article })
def offensive_detail(request, slug):
#return HttpResponse(slug)
offensive_article = Offensive.objects.get(slug=slug)
return render(request, 'articles/offensive_detail.html', { 'offensive_article': offensive_article })
From main folder "website":
ursl.py:
"""website URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url, include
from . import views
from articles import urls
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
from django.conf import settings
from articles import views as article_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^articles/', include('articles.urls')),
url(r'^about/$', views.about),
url(r'^$', article_views.article_list, name="home"),
url(r'^offensive/', include('articles.urls')),
url(r'^$', article_views.offensive_list, name="offensive"),
]
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
base_template.html:
{% load static %}
<!-- Bootstrap CDN -->
<link rel="stylesheet" href="{% static 'styles.css' %}" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat&family=Orbitron:wght#900&display=swap" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<!-- this will apear everywhere -->
<!DOCTYPE html>
<html>
<head>
<title>Articles</title>
<nav class="navbar navbar-dark bg-dark">
<div class="container-fluid">
<!-- Logo -->
<div class="navbar-header">
<!-- <button class="navbar-toggler navbar-toggler-left" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button> -->
<a class="navbar-brand" href="{% url 'home' %}" style="font-family: 'Montserrat', sans-serif; font-family: 'Orbitron',sans-serif; color:red;">Neophyte</a>
</div>
<!-- Item -->
<div>
<ul class="nav navbar-nav">
<li class="active">
<a href="{% url 'offensive' %}" style="font-family: 'Montserrat', sans-serif; font-family: 'Orbitron',sans-serif; color:white"> Offensive
</a>
</li>
</div>
</div>
</nav>
</head>
<body>
<div class="wrapper">
{% block content %}
{% endblock %}
</div>
</body>
</html>
<!-- <img src="{% static 'Neophyte_logo.jpg' %}"/> -->
<!-- href="{% url 'offensive' %}" -->
Your urls seem a bit out of sync. You've got articles.urls included twice and two matching patterns for 'r'^$'.
What you have:
url(r'^admin/', admin.site.urls),
url(r'^articles/', include('articles.urls')),
url(r'^about/$', views.about),
url(r'^$', article_views.article_list, name="home"),
url(r'^offensive/', include('articles.urls')),
url(r'^$', article_views.offensive_list, name="offensive"),
What I think you might want:
url(r'^admin/', admin.site.urls),
url(r'^articles/', include('articles.urls')),
url(r'^offensive/', include('offensive.urls')),
url(r'^about/$', views.about),
# pick one of the following that you want for the root url
# currently will match the first one.
url(r'^$', article_views.article_list, name="home"),
url(r'^$', article_views.offensive_list, name="offensive"),
Or if it is just models separating, put it all in one?
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^articles/', views.article_list, name="article_list"),
url(r"^articles/(?P<slug>[\w-]+)/$", views.article_detail, name="article_detail"),
url(r'^offensive/', views.offensive_list, name="offensive_list"),
url(r"^offensive/(?P<slug>[\w-]+)/$", views.offensive_detail, name="offensive_detail"),
url(r'^about/$', views.about),
url(r'^$', views.about, name="home"),
]
Also, you probably want to be using the newer Path, instead of the url (https://docs.djangoproject.com/en/3.1/topics/http/urls/#example)

Django User Login Issue

I am back again with a Django Question. I am having issues with getting my login screen to work. I feel like maybe this is a simple issue that I am just not seeing. I am using the current versions of Python and Django. I am getting a NoReverseMatch error when trying to access my login page. Here is the code, along with some screen shots:
base.html:
<p>
Learning Log -
Topics -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
log in
{% endif %}
</p>
{% block content %}{% endblock content %}
login.html:
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'users:login' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">log in</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}"/>
</form>
{% endblock content %}
users/urls.py:
from django.urls import path
from django.conf.urls import url
from django.contrib.auth.views import LoginView
from . import views
app_name = 'users'
urlpatterns = [
# Login page
#path('login/', LoginView, {'template_name': 'users/login.html'}, name='login'),
path('login/', LoginView.as_view(template_name='users/login.html')),
]
Code location
Error message
Since you commented out the name='login' part. Django can no longer find a path(…) [Django-doc] with that name hence the error.
You should add the name=… parameter:
# users/urls.py
from django.urls import path
from django.contrib.auth.views import LoginView
from . import views
app_name = 'users'
urlpatterns = [
# Login page
path(
'login/',
LoginView.as_view(template_name='users/login.html'),
name='login' # name of the path
),
]

How to fix: Page not found (404) in django

I'm new in Django. My problem is when I click the title which is in a.html, it's directing me to this URL; http://localhost:8000/aba/R%C3%BCyada%20Aba%20G%C3%B6rmek
in this URL I'm getting an error message; Page not found 404
Here is I wanna do; When I click the title, I wanna show my article details dynamically
dreamarticle/urls.py
from django.contrib import admin
from django.urls import path, re_path
from dreamarticle import views
app_name = "Dreamarticle"
urlpatterns = [
re_path('/aba/(.*?)/',views.aba,name="aba"),
path('a/',views.a,name="a"),
]
blog/urls.py
from django.contrib import admin
from django.urls import path,include
from article import views
from dreamarticle import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name="index"),
path('articles/',include("article.urls")),
path('user/',include("user.urls")),
path('dreamarticle/',include("dreamarticle.urls")),
]
dreamarticle/views.py
def aba(request, title):
context = dict()
context.update(
dreamarticlesaba=get_object_or_404(dreamarticle, title=title),
)
return render(request, "aba.html", context)
aba.html
{% extends "layout.html" %}
{% block body%}
<!-- Content here -->
<br>
<div class="container">
<div class="row">
{% if dreamarticlesaba %}
{% for dreamarticle in dreamarticlesaba %}
<div class="col-md-12 dreamdetail">
<h1>{{dreamarticle.title}}</h1>
<hr>
<p>{{dreamarticle.content|safe|escape}}<p>
</div>
{% endfor %}
{% endif %}
</div>
</div>
a.html
{% extends "layout.html" %}
{% block body%}
{% include "includes/searchbar.html" %}
<!-- Content here -->
<br>
<div class="container">
<div class="row">
{% if dreamarticles %}
{% for dreamarticle in dreamarticles %}
<div class="col-md-4 text-center bg-primary">
<br><b>{{dreamarticle.title}}</b>
<b>{{dreamarticle.title}}</b>
</a>
</div>
{% endfor %}
{% endif %}
</div>
</div>
{% endblock body%}
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/aba/R%C3%BCyada%20Aba%20G%C3%B6rmek
Using the URLconf defined in blog.urls, Django tried these URL patterns, in this order:
admin/
[name='index']
articles/
user/
dreamarticle/
The current path, aba/Rüyada Aba Görmek, didn't match any of these.
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.

When we extend an allauth view and create a new url based on that view is the old "/accounts/*" URLs of django allauth still required?

I extended the SignupView of django-allauth and created a url "/account-signup/" and also some minor changes in the template and I'm using the url name of my url. So, it keeps showing error that:
NoReverseMatch at /account-signup/
Reverse for 'account_login' not found. 'account_login' is not a valid view function or pattern name.
I've tried searching where the url name account_login is used in the template. Also, I've tried enabling the default URLs given by django allauth. It doesnt show error when the allauth URLs are included in the urls.py file.
/signup.html
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Signup" %}{% endblock %}
{% block content %}
<h1>{% trans "Sign Up" %}</h1>
<p>{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}</p>
<p>some content from sugat</p>
<form class="signup" id="signup_form" method="post" action="{% url 'my_app:custom_signup' %}">
{% csrf_token %}
{{ form.as_p }}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button type="submit">{% trans "Sign Up" %} »</button>
</form>
{% endblock %}
/my_app/urls.py
from django.conf.urls import url
from .views import *
app_name = "my_app"
urlpatterns = [
url(r'^account-signup/$', AccountSignUp.as_view(), name="account_signup"),
]
/myproject/urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'^accounts/', include('allauth.urls')),
url(r'', include("my_app.urls")),
]

Error: 'login' not found. 'login' is not a valid view function or pattern name

This is the first time I am using Django login template and I ran into a problem. It keeps saying that login is not a valid view function but I define it in the urls.py in my users app:
Not sure what I am doing wrong.
main urls.py
urlpatterns = [
path('', include('blogging_logs.urls', namespace='blogging_logs')),
path('users/', include('users.urls', namespace='users')),
path('admin/', admin.site.urls),
]
app: blogging_logs: base.html
<p>
Home
Categories
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
login in
{% endif %}
</p>
{% block content %}{% endblock content %}
app: users: urls.py
from django.contrib import admin
from django.urls import re_path, path
from django.contrib.auth import authenticate, login
from django.contrib.auth import views as auth_views
app_name = 'users'
urlpatterns = [
# Login Page
path('login/', auth_views.LoginView.as_view(template_name='login.html')),
]
app:users: login.html
{% extends "blogging_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password din't match. Please try again.</p>
{% endif %}
<form class="" method="post" action="{% url 'users:login' %}" >
{% csrf_token %}
{{ form.as_p }}
<button name='submit'> Login in </button>
<input type="hidden" name="next" value="{% url 'blogging_logs:index' %}" />
</form>
{% endblock content %}
You are missing the name argument for the path function:
Change the following line
path('login/', auth_views.LoginView.as_view(template_name='login.html')),
to
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'),

Categories