This question already has answers here:
How to display images from model in Django?
(3 answers)
Closed 5 years ago.
I don't know why the images aren't showing in Django. Something to do with the media root?
settings code
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')'
models code
from django.db import models
from django.core.urlresolvers import reverse
Create your models here.
class Post(models.Model):
## Post Properties
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
summary = models.CharField(max_length=255)
content = models.TextField()
published = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='img',default='media/placeholder.png')
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.title
def get_absolute_url(self):
return reverse('blog.views.post', args=[self.slug])
I didn't add a url for the picture, could that be a problem?
urls
urlpatterns = [
url(r'^post/(.*)', blogViews.post),
url(r'^about/$', blogViews.about),
url(r'^$', blogViews.index),
url(r'^admin/', admin.site.urls),
index.html code
<img src="{{post.image}}">
<p> {{post.image}} </p>
**Views.py **
from django.shortcuts import render, render_to_response, get_object_or_404
from django.http import HttpResponse
from .models import Post
# Create your views here.
def index(request):
posts = Post.objects.all()
return render(request, 'index.html', {'posts': posts})
def post(request, slug):
return render_to_response('post.html', {
'post': get_object_or_404(Post,slug=slug)
})
def about(request):
return render(request, 'about.html', {})
In the website all that shows is a blank picture as well as the file name (either 'placeholder.png' which is the default or img/... which I uploaded through admin)
Edit:
This was marked as a duplicate, I saw that post and tried to change my code to reflect that code but it wasn't working. Figured it would be better to post my own.
Thanks in advance, first question on this site!
Try this,
<img src="{{post.image.url}}">
Also, add in your urls.py,
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
For learning more about serving static, refer the documentation here...
Related
I am trying to build a website on cPanel using django. My models were working fine untill I created my first html page and tried to render it. Now whenever I try to load my site I get "AttributeError at /admin/
module 'artclBlog.views' has no attribute 'home'" pic of error message
my views.py
from django.shortcuts import render, get_object_or_404
from .models import Blog
def home(request):
blogs = Blog.objects.order_by('-date')
return render(request, 'blog/home.html', {'blogs': blogs})
my urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from artclBlog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
path('blog/', include('blog.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
my models.py
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=200, default='')
summary = models.CharField(max_length=200, default='')
pageOne = models.TextField(default='')
pageTwo = models.TextField(default='')
pageThree = models.TextField(default='')
pageFour = models.TextField(default='')
date = models.DateField(default='')
def __str__(self):
return self.title
I am creating an app in Django which have two external users:
1. Teacher
2. Student
I have to create total of 3 apps, one the base app that contains home.html template, other the student app that contains student.html template and third teacher app that contains teacher.html template.
I have just created two apps for now, base app and student app, I have created login, logout and register pages for student app, now I am successfully able to redirect the user (student) to the student.html whenever the student logs into the system and I did this by putting LOGIN_REDIRECT_URL = 'student' in my settings.py.
I want to do the same for Teacher app as well but I want to redirect teacher to the teacher.html.
Is there any way that I can create the second LOGIN_REDIRECT_URL in settings.py to fulfil this purpose or it will be done any other way?
My Project Structure
django_project
|__esacp(main system)
|_____migrations
|_____templates
|________esacp
|__________base.html
|__________home.html
|__________student.html
|__________teacher.html
|_____apps.py
|_____forms.py
|_____models.py
|_____views.py
|__django_project
|__student
|_____migrations
|_____templates
|________student
|___________login.html
|___________logout.html
|___________register.html
|_____apps.py
|_____forms.py
|_____models.py
|_____views.py
|__teacher
|__db.sqlite3
|__manage.py
Code of models.py of esacp app
from django.db import models
from django.utils import timezone
class StudentType(models.Model):
studenttype_id = models.IntegerField(primary_key=True)
type_title = models.CharField(max_length=50)
def __str__(self):
return self.type_title
class StudentDetails(models.Model):
name = models.CharField(max_length=50)
username = models.CharField(max_length=50, primary_key=True)
password = models.CharField(max_length=50)
email_id = models.CharField(max_length=100)
contact = models.CharField(max_length=100)
studenttype = models.ForeignKey(StudentType, on_delete=models.CASCADE)
registration_date = models.DateTimeField(default=timezone.now)
modify_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Code of urls.py of esacp app
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='esacp-home'),
path('student', views.student, name='student'),
]
Code of urls.py of main project
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path, include
from users import views as user_views
urlpatterns = [
path('admin/', admin.site.urls),
path('register/', user_views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
path('tlogin/', auth_views.LoginView.as_view(template_name='teacher/tlogin.html'), name='tlogin'),
path('tlogout/', auth_views.LogoutView.as_view(template_name='teacher/tlogout.html'), name='tlogout'),
path('esacp/', include('esacp.urls')),
Code of views.py of teacher app
from django.shortcuts import render
from django.contrib.auth.views import LoginView
class MyLoginView():
def get_success_url(self):
url = self.get_redirect_url()
return url
Code of views.py of esacp app
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
def home(request):
return render(request, 'esacp/home.html')
#login_required
def student(request):
return render(request, 'esacp/student.html')
and below I have the statement in setting.py
LOGIN_REDIRECT_URL = 'student'
You have two login URLs. Therefore you can use a different login view for each one, and override get_success_url so that you are redirected to the correct page after login.
For example, the teacher login view would look something like:
from django.contrib.auth.views import LoginView
class TeacherLoginView(LoginView):
template_name = 'teacher/tlogin.html'
def get_success_url(self):
url = self.get_redirect_url()
return url or '/teacher/' # FIXME use reverse here instead of hardcoding the URL
Then use that view instead of TeacherView in your URL patterns.
path('login/', TeacherLoginView.as_view(), name='login'),
I have a question, I wrote peace of Djnago code, to upload profile picture for user, from admin area model works fine, but from website itself image cannot be uploaded, it seems that code is not even being called. Here is my code, could you check and tell me what might be wrong?
models.py:
from django.conf import settings
from django.db import models
from django.core.files import File
def upload_location(instance, filename):
location = str(instance.user.id)
return "%s/%s" %(location, filename)
class ProfilePicture(models.Model):
user = models.ForeignKey(User)
profile_picture = models.ImageField(upload_to=upload_location, null=True, blank=True)
def __unicode__(self):
return unicode(self.user.id)
forms.py:
from django import forms
from .models import ProfilePicture
class ProfileEditPicture(forms.ModelForm):
class Meta:
model = ProfilePicture
fields = [
"profile_picture"
]
views.py:
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.shortcuts import render, get_object_or_404, render_to_response
rom .forms import ProfileEditPicture
from .models import ProfilePicture
#login_required()
def profile_picture(request, id):
user = get_object_or_404(User, id=id)
title = "Profile Edit"
profile, created = Profile.objects.get_or_create(user=user)
form = ProfileEditPicture(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
context = {
"form":form,
"title":title,
"profile":profile
}
return render(request, "profile/form.html", context)
urls.py:
urlpatterns = [
...
url(r'^profile_picture/(?P<id>[\w.#+-]+)/', 'profiles.views.profile_picture', name='profile_picture'),
...
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
HTML code in template is default django form.
Thanks in advance :)
A useful piece of documentation is "Binding uploaded files to a form". Possibly if you follow this you will overcome your issue.
Among other things, it is important that include this attribute in your forms element:
<form method="post" action="..." enctype="multipart/form-data">
categories.html # this is what i want to be called by CategoryView.as_view() which never works. Howevwer index.html works but i have hardcoded the link as follows within index.html. Although index.html extends base.html which is where am outputing the url.
Edit: Avoid confusion this is what is available in index.html template which i guess should work but shows the following error for index now Page not found (404)
<li>All</li>
from my root directory when i type http://127.0.0.1:8000 it works but i want something like this http://127.0.0.1:8000/cartegories/(index.html or categories.html) i assume the index.html or categories.html is not visible when typed, which is fine.
I can’t believe this is taking me 12hours with all possible intuitive tweaking still can’t get it to work. Please someone advise what am doing wrong. In essense i am just outputing hellow world in categories.html but later i would iterate through and list all the categories in my blog… if hello world can’t work then nothing will..
#posts urls.py
from django.conf.urls import include, url
from django.contrib import admin
from .views import IndexView, CategoryView
urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'),
url(r'^all_categories$', CategoryView.as_view(), name='all_categories'),
# stuff i have tried
]
#admin urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^/', include('posts.urls', namespace="posts")),
url(r'^admin/', include(admin.site.urls)),
]
#views.py
from django.shortcuts import render
from .models import Post, Comment, Category, Reply
from django.views import generic
class IndexView(generic.ListView):
template_name = 'posts/index.html'
context_object_name = 'posts'
model = Post
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
class CategoryView(generic.ListView):
template_name = 'posts/categories.html'
context_object_name = 'categories'
model = Category
#modesl.py
class Category(models.Model):
category_name = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.category_name
def get_absolute_url(self):
return reverse('all_categories')
class Post(models.Model):
title = models.CharField(max_length=200)
…
category = models.ForeignKey(Category)
def save(self, *args, **kargs):
if not self.id:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kargs)
def __str__(self):
return self.title
Changing the order of the URLs in the files solved the problem. Generally, the order of the main urls.py is important for readability but the / slash did the trick
#admin urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^/', include('posts.urls', namespace="posts")),
url(r'^admin/', include(admin.site.urls)),
]
Also in the post/url.py file i added a / at the end of the regex
urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'),
url(r'^categories/$', CategoryView.as_view(), name='all_categories'),
]
Finally in the template the html read as follows:
<li>All</li>
I think I done everything correct but I don't know why it doesn't work. When I try to reach a page I get error "Page not found (404)".
So, this all products page works 127.0.0.1:8000/products/ but when I try to visit single product page 127.0.0.1:8000/products/audi I get error that it's not found...
So, maybe you what's wrong here?
Thank you.
Page not found (404)
Request Method: GET
Request URL: http://link/products/audi
Using the URLconf defined in ecommerce.urls, Django tried these URL patterns, in this order:
^static/(?P<path>.*)$
^media/(?P<path>.*)$
^admin/doc/
^admin/
^products/ ^$ [name='products']
^products/ ^$(?P<slug>.*)/$
^contact/ [name='contact_us']
The current URL, products/audi, didn't match any of these.
Main project urls.py:
from django.conf import settings
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT
}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT
}),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^products/', include('products.urls')),
url(r'^contact/', 'contact.views.contact_us', name='contact_us'),
)
Products app urls.py:
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('products.views',
url(r'^$', 'all_products', name='products'),
url(r'^$(?P<slug>.*)/$', 'single_product'),
)
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, RequestContext, get_object_or_404
from .models import Product
def all_products(request):
products = Product.objects.filter(active=True)
return render_to_response('products/all.html', locals(), context_instance=RequestContext(request))
def single_product(request, slug):
product = get_object_or_404(Product, slug=slug)
return render_to_response('products/single.html', locals(), context_instance=RequestContext(request))
models.py
from django.db import models
# Create your models here.
class Product(models.Model):
title = models.CharField(max_length=220)
description = models.CharField(max_length=3000, null=True, blank=True)
price = models.DecimalField(max_digits=1000, decimal_places=2, null=True, blank=True)
slug = models.SlugField()
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __unicode__(self):
return self.title
class Meta:
ordering = ['title',]
class ProductImage(models.Model):
product = models.ForeignKey(Product)
description = models.CharField(max_length=3000, null=True, blank=True)
image = models.ImageField(upload_to='product/images/')
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __unicode__(self):
return self.image
Your URL pattern has an extra $ at the beginning, so it can never match anything:
url(r'^$(?P<slug>.*)/$', 'single_product')
This should be:
url(r'^(?P<slug>.*)/$', 'single_product')
This still requires a trailing slash, which is the normal pattern. With that corrected, your URL should be /products/audi/. You don't show the context in which that URL is created, but this is one example of why it's a good idea to use Django's url reversal to build URLs if at all possible. That would look something like this, in Python code (for instance, possibly in a get_absolute_url method on the model:
reverse('single_product', kwargs={'slug': someproduct.slug})
Or like this, in a template:
Django 1.5:
{% url 'single_product' someproduct.slug %}
Django 1.4 and earlier:
{% url single_product someproduct.slug %}
You have a typo:
url(r'^$(?P<slug>.*)/$', 'single_product'),
Note this $ just after ^, in regexp it states for a string end. Replace with
url(r'^(?P<slug>.*)/$', 'single_product'),