django upload image file from templates - django

every one ,,I can upload image from admin site,, but do not know how to upload image from the templates,,
models.py
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
from django.utils import timezone
def get_imagep_Product(instance, filename):
return '/'.join(['products', instance.slug, filename])
class ProductsTbl(models.Model):
model_number = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, null=True)
material = models.TextField(blank=True, null=True)
feature = models.TextField(blank=True, null=True)
created = models.DateTimeField(editable=False)
modified = models.DateTimeField(auto_now=True)
release = models.DateTimeField(blank=True, null=True)
submit_date = models.DateTimeField(blank=True, null=True)
slug = models.SlugField(unique=True)
user = models.ForeignKey(User, blank=True, null=True)
image = models.ImageField(upload_to=get_imagep_Product, blank=True) #image file
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.created = timezone.now()
return super(ProductsTbl, self).save(*args, **kwargs)
views.py
from django.shortcuts import render,redirect
from .forms import ProductsTblForm
from .models import ProductsTbl
from django.template.defaultfilters import slugify
from django.contrib.auth.decorators import login_required
from django.http import Http404,HttpResponse
import datetime
def create_thing(request):
form_class = ProductsTblForm
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
thing = form.save(commit=False)
thing.user = request.user
thing.slug = slugify(thing.model_number)
thing.save()
return redirect('thing_detail', slug=thing.slug)
else:
form = form_class()
return render(request, 'things/create_thing.html', { 'form': form,})
urls.py
from django.conf.urls import patterns, url,include
from django.contrib import admin
from django.views.generic import TemplateView
from designer import views
from designer.backends import MyRegistrationView
from django.conf import settings
urlpatterns = [
url(r'^create_thing/$', views.create_thing, name='create_thing'),
]
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
]
forms.py
from django.forms import ModelForm
from .models import ProductsTbl
class ProductsTblForm(ModelForm):
class Meta:
model = ProductsTbl
fields = ('model_number','name','feature', 'material','release','image',)
create_thing.html
{% extends 'base.html' %} {% block title %}
Create a Thing - {{ block.super }} {% endblock title %}
{% block content %}
<h1>Create a Thing</h1>
<form role="form" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
when I click the create things I can see form here,,however I do not know how can let the image upload
I have looking for this link ,,however I do not know how to let it work in my app,,

First, you will need to add enctype="multipart/form-data" in your <form> definition. As this is required for file uploads.
<form role="form" action="" method="post" enctype="multipart/form-data">
Second, instead of form_class(request.POST) you will need to create form in your view by passing request.FILES too.
form_class(request.POST, request.FILES)

Related

How to solve error message: no such column: auctions_auction.image_url

I'm creating an aunction website where users will submit a form with the link to an image when creating a new listing. This link/url will then be converted and displayed as an image on the website. I keep getting this error when I upload the details of the form including the link to the image -
""OperationalError at /create/
no such column: auctions_auction.image_url.""
How can I clear this error?
VIEWS.PY
from django.shortcuts import render, redirect
from .forms import AuctionForm
def create_listing(request):
form = AuctionForm()
if request.method == 'POST':
form = AuctionForm(request.POST, request.FILES)
if form.is_valid:
form.save()
return redirect('index')
else:
form = AuctionForm()
context = {'form': form}
return render(request, 'auctions/create-listing.html', context)
FORMS.PY
from .models import Auction
from django import forms
from django.forms import fields
class AuctionForm(forms.ModelForm):
class Meta:
model = Auction
fields = ['title', 'description', 'current_bid', 'image_url']
MODELS.PY
from django.db import models
from django.core.files import File
from urllib.request import urlopen
from tempfile import NamedTemporaryFile
class Auction(models.Model):
title = models.CharField(max_length=25)
description = models.TextField()
current_bid = models.IntegerField(null=False, blank=False)
users_bid = models.IntegerField(null=False, blank=False)
image_upload = models.ImageField(upload_to='images/')
image_url = models.URLField(verbose_name="URL", max_length=255, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
if self.image_url and not self.image_upload:
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(urlopen(self.image_url).read())
img_temp.flush()
self.image_upload.save(f"image_{self.pk}", File(img_temp))
super(self).save(*args, **kwargs)
def __str__(self):
return self.title
HTML
{% extends "auctions/layout.html" %}
{% block body %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
{% endblock %}
URLS.PY
urlpatterns = [
path("create/", views.create_listing, name="create_listing")
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
You have to migrate your model changes into the database. This might work:
$ python manage.py makemigrations
$ python manage.py migrate

Django Page not found (404) when filter services by categories using urls

I'm learning how to use urls in Django and I have a problem. I'm trying to get all services that belongs to a category by clicking on the category link, but when I do that, the browser returns me this error:
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/services/None
Raised by: services_app.views.service_list
No Category matches the given query.
And the url looks:
http://localhost:8000/services/None
I already have a populated data base, and it can display their content just using a djanfo for, but I need it to be displayed by categories. Can anyone help me?
Here are my files:
home_app/models.py
from django.db import models
from django.urls import reverse
class Category(models.Model):
name=models.CharField(primary_key=True, max_length=50)
slug=models.SlugField(unique=True, blank=True, null=True)
image=models.ImageField(upload_to='category_home')
description=models.CharField(max_length=100)
content=models.TextField(max_length=500, default="Service")
created=models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('services_by_category', args=[self.slug])
services_app/models.py
from django.db import models
from home_app.models import Category
class Services(models.Model):
category=models.ForeignKey(Category, on_delete=models.CASCADE)
title=models.CharField(max_length=50)
completed=models.DateField(auto_now_add=False, null=True, blank=True)
content=models.CharField(max_length=50, null=True, blank=True)
image=models.ImageField(upload_to='services_services')
created=models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Service'
verbose_name_plural = 'Services'
def __str__(self):
return '%s de %s' % (self.category, self.title)
services_app/views.py
from django.shortcuts import render, get_object_or_404
from .models import Services
from home_app.models import Category
def service_list(request,category_slug=None):
category = None
categories = Category.objects.all()
services = Services.objects.all()
if category_slug:
category = get_object_or_404(Category,slug=category_slug)
services = services.filter(category=category)
return render(request, 'services_app/services.html', {'categories':categories, 'category':category, 'services':services,})
services_app/urls.py
from django.urls import path
from services_app import views
urlpatterns = [
path('', views.service_list, name='Services'),
path('<slug:category_slug>', views.service_list, name='services_by_category'),
]
services_app/templates/services_app/services.html
{% extends "home_app/base.html" %}
{% load static %}
{% block content %}
<div id="sidebar">
<br>
<br>
<h3>Categories</h3>
<ul>
{% for c in categories %}
<li>
<h4>{{ c.name }}</h4>
</li>
{% endfor %}
</ul>
</div><br>
<div>
<h1>{% if category %}{{ category.name }}{% endif %}</h1>
{% for service in services %}
<img src="{{service.image.url}}">
{% endfor %}
</div>
{% endblock %}
Also my main urls:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home_app.urls')),
path('services/', include('services_app.urls')),
path('contact/', include('contact_app.urls')),
]
The problem is you don' t generate the slug of Category:
from django.db import models
from django.urls import reverse
from django.utils.text import slugify
class Category(models.Model):
name=models.CharField(primary_key=True, max_length=50)
slug=models.SlugField(unique=True, blank=True, null=True)
image=models.ImageField(upload_to='category_home')
description=models.CharField(max_length=100)
content=models.TextField(max_length=500, default="Service")
created=models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def save(self, *args, **kwargs):
if self._state.adding:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('services_by_category', args=[self.slug])
Note that you need to set manually the slug of the
existing Category instances (with the admin, a shell or a migration), or you can simply recreate them.

Getting Image in django teplate from ManyToMany field

It is returning an error : Not Found: /post-detail/6/images/wallpaper002.jpg. I have tried to show image through {{ post_detail.img.all.first.url }} but I could show image in the template, it returns None value.
news.html
'''
<div class="text-center">
<img class="detail_picture img-thumbnail" src="{{ post_detail.img.all.first }}">
</div>
'''
models.py
'''
class Pictures(TimestampedModel):
img = models.ImageField(upload_to='images')
def __str__(self):
return str(self.img)
class Post(TimestampedModel):
title = models.CharField(max_length=128)
lang = models.IntegerField(choices=LANGUAGES, default=1)
short_description = models.CharField(max_length=255, blank=True, null=True)
description = models.TextField(blank=True, null=True)
category = models.ManyToManyField(PostCategoies, blank=True)
img = models.ManyToManyField(Pictures, blank=True)
icon = models.CharField(max_length=128, blank=True, null=True, help_text="Example: fa fa-info")
is_active = models.BooleanField(default=True)
def __str__(self):
return self.title
'''
views.py
'''
from django.shortcuts import render, redirect
from django.contrib import messages
from django.views import View
from .models import Post, Pictures
from django.views.generic import DetailView
from . import models
from django.shortcuts import get_object_or_404
class HomePageView(View):
def get(self, request):
posts = Post.objects.all()[:4]
context = {'posts': posts}
return render(request, 'index.html', context)
class PostDetailView(DetailView):
context_object_name = "post_detail"
model = models.Post
template_name = 'news.html'
'''
urls.py
'''
app_name = 'posts'
urlpatterns = [
path('', HomePageView.as_view(), name=""),
path('post-detail/<int:pk>/', PostDetailView.as_view(), name="post_detail")
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
'''
You are accessing the instance of a Pictures class with your current code. You need to then access the img property:
<div class="text-center">
<img class="detail_picture img-thumbnail" src="{{ post_detail.img.all.first.img.url }}">
</div>
I would also suggest that you protect against the case of not having an instance in the ManyToMany field
{% if post_detail.img.all.first %}
<div class="text-center">
<img class="detail_picture img-thumbnail" src="{{ post_detail.img.all.first.img.url }}">
</div>
{% endif %}
I'd also suggest looking into prefetch_related and/or Subquery as a way to more efficiently fetch these related details. It will help you prevent N+1 queries. You can verify you're not running too many queries with the django debug toolbar.

Error uploading file in django

I am trying to attach a file in django models, but when I hit submit button the selected file immediately disappears and the form submission fails . What is going wrong here?
forms.py
from django import forms
from .models import IssueNotice
class IssueNoticeForm(forms.ModelForm):
class Meta:
model = IssueNotice
fields = ('title', 'content','issuer','attachment',)
models.py
from django.db import models
from django.utils import timezone
from django import forms
class IssueNotice(models.Model):
title = models.CharField(max_length=300)
content = models.TextField()
attachment = models.FileField(upload_to='attachments')
issuer = models.CharField(max_length=100)
issuer_id = models.ForeignKey('auth.User')
issued_date = models.DateTimeField(default = timezone.now)
def publish(self):
self.issued_date = timezone.now()
self.save()
def __str__(self):
return self.title
views.py
from django.shortcuts import render
from django.utils import timezone
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from .models import IssueNotice
from .forms import IssueNoticeForm
def issue_notice(request):
if request.method == "POST":
form = IssueNoticeForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['attachment'])
notice = form.save(commit = False)
notice.issuer_id = request.user
notice.issued_date = timezone.now()
notice.save()
return redirect('home_page')
else:
form = IssueNoticeForm()
return render(request, 'webadmin/issue_notice.html',{'form':form})
issue_notice.html
{% extends 'webadmin/base.html' %}
{% block content %}
<div class="col-md-8">
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Issue</button>
</form>
{% endblock %}

Creating forms from models

i'm moving my first steps into Django and i'm tryin' to follow the tutorial at this link: https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
but i can't get a form. It just returns a white page!
Can someone explain if i'm missing something?
my models.py:
from django.db import models
from django.forms import ModelForm
class UserProfile(models.Model):
name = models.CharField(max_length=30)
surname = models.CharField(max_length=30)
email = models.EmailField()
tel = models.CharField(max_length=30, null=True, blank=True)
def __unicode__(self):
return '%s %s' % (self.surname, self.name)
class Ad(models.Model):
title = models.CharField(max_length=50)
descr = models.TextField()
city = models.CharField(max_length=30)
price = models.FloatField(null=True, blank=True)
img = models.ImageField(upload_to='./uploaded_imgs', null=True, blank=True)
dateIn = models.DateField(auto_now_add=True)
dateExp = models.DateField(auto_now_add=True)
codC = models.ForeignKey('Cat')
codU = models.ForeignKey('UserProfile')
def __unicode__(self):
return '%s - %s' % (self.title, self.dateIn)
class Cat(models.Model):
cat = models.CharField(max_length=35, primary_key=True)
def __unicode__(self):
return self.cat
my forms.py:
from django import forms
class newAdForm(forms.Form):
title = forms.CharField(max_length=50)
descr = forms.CharField(widget=forms.Textarea)
city = forms.CharField(max_length=30)
price = forms.FloatField(required=False)
img = forms.ImageField(required=False)
dateIn = forms.DateField(auto_now_add=True)
dateExp = forms.DateField(auto_now_add=True)
codC = forms.ModelChoiceField(Cat)
codU = forms.ModelChoiceField(UserProfile)
my views.py:
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
from django.http import HttpResponse
from django import forms
from models import *
from django.forms import *
from django.forms.models import modelformset_factory
[...]
def newAd(request):
newAdFormSet = modelformset_factory(Ad)
if request.method == 'POST':
formset = newAdFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
return render_to_response('conf.html', {'state':'Your ad has been successfull created.'}, context_instance = RequestContext(request),)
else:
formset = newAdFormSet()
return render_to_response('ad_form.html', context_instance = RequestContext(request),)
my ad_form_auto.html template:
{% extends "base.html" %}
{% block title %}Ads insertion form{% endblock %}
{% block content %}
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form method="post" action="">
{{ formset }}
</form>
{% endblock %}
Thanks a lot! This community looks just awesome! :)
You're not passing the form to the template - at present your 'formset' variable containing the form isn't included in the datadict being passed to the view.
return render_to_response('ad_form.html', context_instance = RequestContext(request),)
Should include the data (see render_to_response() docs) here I've renamed the form in your data and to your template as 'form' for ease of nomenclature:
return render_to_response('ad_form.html',
{'form':formset},
context_instance=RequestContext(request))
Then, in your template (see forms in templates docs) replace {{formset}} with {{form.as_p}}. Also add a submit button to the form.
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>