Uploading multiple images in Django with django-multiupload library - django

I'm trying to use the below library to implement multi upload in my Django proejct.
https://github.com/Chive/django-multiupload
boutique/models.py
class Photo(models.Model):
store = models.ForeignKey(Store)
photo = models.FileField(null=True, blank=True, upload_to='boutique/index/%Y/%m/%d')
url = models.CharField(max_length=40, null=True, blank=True, verbose_name='Image URL')
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return str(self.photo)
def get_absolute_url(self):
return reverse('cms:photo_edit', args=[self.pk])
cms/forms.py
from django import forms
from boutique.models import Photo
from multiupload.fields import MultiFileField
class PhotoCreateForm(forms.ModelForm):
class Meta:
model = Photo
fields = ['store']
attachments = MultiFileField(min_num=1, max_num=3, max_file_size=1024*1024*5)
cms/views.py
class PhotoCreateView(FormView):
model=Photo
template_name='cms/photo_new.html'
form_class = PhotoCreateForm
success_url=reverse_lazy('cms:photo')
queryset = Photo.objects.all()
def form_valid(self, form):
for each in form.cleaned_data['attachments']:
Attachment.objects.create(file=each)
return super(PhotoCreateView, self).form_valid(form)
cms/photo_new.html
{% extends 'cms/base.html' %}
{% load staticfiles %}
{% block page-header %}Add Photo{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table class="table table-hover store-form">
{{ form.as_table }}
</table>
<input class="btn btn-success btn-block" type="submit" name="" value="Submit">
<br>
</form>
{% endblock %}
FYI, I'm not using Django default admin, but my own customized admin, which is the app named cms. I'm also using models in the app named boutique.
When I upload photos, nothing happens and the page doesn't even move to the success url. After submitting the files, the file input field just says "Thie field is required", and I don't see any uploads on the database.
Is there something wrong on my codes?

Your Model name is Photo, then why you try to save photos at Attachment Model!
cms/views.py
class PhotoCreateView(FormView):
model=Photo
template_name='cms/photo_new.html'
form_class = PhotoCreateForm
success_url=reverse_lazy('cms:photo')
queryset = Photo.objects.all()
def form_valid(self, form):
for each in form.cleaned_data['attachments']:
Photo.objects.create(photo=each)
return super(PhotoCreateView, self).form_valid(form)
If you want to upload any file or image then you need to add enctype="multipart/form-data" to your HTML form.
cms/photo_new.html
{% extends 'cms/base.html' %}
{% load staticfiles %}
{% block page-header %}Add Photo{% endblock %}
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table class="table table-hover store-form">
{{ form.as_table }}
</table>
<input class="btn btn-success btn-block" type="submit" name="" value="Submit">
<br>
</form>
{% endblock %}
Update this two file. hopefully, it'll work. If not then let me know.

Related

uploading multiple files in django form and function in views

I am trying to upload multiple files in Django form. I followed multiple methods. I am successful via models to views but I want via models to forms to views. I followed Use view/form in Django to upload a multiple files this question but my form is not submitting. Here I am sharing my codes. I hope to get the mistake I am doing by any expert.
#models.py
class Question(models.Model):
description = models.TextField(blank=True, null=True)
created_by = models.ForeignKey(User, blank=False, on_delete=models.CASCADE)
def __str__(self):
return self.description
class QuestionFile(models.Model):
question = models.ForeignKey(
Question, on_delete=models.CASCADE, related_name='files', null=True, blank=True)
file = models.FileField(
'files', upload_to=path_and_rename, max_length=500, null=True, blank=True)
def __str__(self):
return str(self.question)
#forms.py
from django import forms
from .models import *
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['description']
class QuestionFileForm(QuestionForm): # extending Questionform
file = forms.FileField(
widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta(QuestionForm.Meta):
fields = QuestionForm.Meta.fields + ['file', ]
def clean(self):
cleaned_data = super().clean()
description = cleaned_data.get("description")
file = cleaned_data.get("file")
if not description and not file:
self.add_error(
'description', 'Kindly describe the question details or upload any file')
#views.py
def questionView(request):
if request.method == 'POST':
form = QuestionFileForm(request.POST or None, request.FILES or None)
files = request.FILES.getlist('file')
if form.is_valid():
question = form.save(commit=False)
question.created_by = request.user
# add everything needed to add here
question.save()
if files: # check if user has uploaded some files
for file in files:
QuestionFile.objects.create(question=question, file=file)
messages.success(request, 'Question asked successfully.')
return redirect('url_name')
else:
form = QuestionFileForm()
context = {
"page_title": "Ask a Math Question",
"form": form
}
return render(request, 'template.html', context)
#template.html
{% extends 'base.html' %}
<!-- title -->
{% block title %}{{ page_title }}{% endblock title %}
<!-- body -->
{% block content %}
<div class="ask_question text-center">
<!--for message-->
{% if messages %} {% for message in messages %}
<div
{% if message.tags %}
class="alert alert-{{ message.tags }} text-center"
{% endif %}
>
{{ message }}
</div>
{% endfor %} {% endif %}
<form
method="POST"
action="{% url 'fask_question' %}"
novalidate
class="needs-validation"
enctype="multipart/form-data"
>
{% csrf_token %}
<div class="mb-3">
<input
type="file"
class="clearablefileinput form-control-file"
name="files"
id="exampleFormControlFile1"
multiple
/>
</div>
<div class="mb-3">
<textarea
class="form-control"
id="exampleFormControlTextarea1"
rows="8"
placeholder="Type your question here"
name="description"
></textarea>
</div>
<button type="submit" class="btn">Submit</button>
</form>
</div>
{% endblock %}
I am unable to understand where I am making the mistake that my form is not submitting.
If anyone can help I will be grateful.
Thanks in advance.
Try to pass the form from the context in to the template
Change this part of your template
<form
method="POST"
action="{% url 'fask_question' %}"
novalidate
class="needs-validation"
enctype="multipart/form-data"
>
{% csrf_token %}
<div class="mb-3">
<input
type="file"
class="clearablefileinput form-control-file"
name="files"
id="exampleFormControlFile1"
multiple
/>
</div>
<div class="mb-3">
<textarea
class="form-control"
id="exampleFormControlTextarea1"
rows="8"
placeholder="Type your question here"
name="description"
></textarea>
</div>
<button type="submit" class="btn">Submit</button>
</form>
To
<form
method="POST"
action="{% url 'fask_question' %}"
novalidate
class="needs-validation"
enctype="multipart/form-data"
>
{% csrf_token %}
{{ form }}
<button type="submit" class="btn">Submit</button>
</form>

Edit item within views in Django

There is some problem, I'm trying to update the product on the client by making changes and clicking on the update button - my page is refreshing w/o updating info, so the product has the same data as before. But in the logs, the status code of the GET request is 200 and shows the updated object in the database. When I try to update through the admin Django dashboard, everything works successfully, the problem is only on the client side of the web application. What issues can there be?
Thank you in advance!
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
CATEGORY = (
('Stationary', 'Stationary'),
('Electronics', 'Electronics'),
('Food', 'Food'),
)
class Product(models.Model):
name = models.CharField(max_length=100, null=True)
quantity = models.PositiveIntegerField(null=True)
category = models.CharField(max_length=50, choices=CATEGORY, null=True)
def __str__(self):
return f'{self.name}'
class Order(models.Model):
name = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
customer = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
order_quantity = models.PositiveIntegerField(null=True)
def __str__(self):
return f'{self.customer}-{self.name}'
views.py
#login_required(login_url='user-login')
#allowed_users(allowed_roles=['Admin'])
def product_edit(request, pk):
item = Product.objects.get(id=pk)
if request.method == 'POST':
form = ProductForm(request.POST, instance=item)
if form.is_valid():
form.save()
return redirect('dashboard-products')
else:
form = ProductForm(instance=item)
context = {
'form': form,
}
return render(request, 'dashboard/products_edit.html', context)
forms.py
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = '__all__'
html template:
{% extends 'partials/base.html' %}
{% block title %}Products Edit Page{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row my-4">
<div class="col-md-6 offset-md-3 p-3 bg-white">
<h3>Edit Item</h3>
<hr>
<form>
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-info" type="submit" value="Confirm">
</form>
</div>
</div>
{% endblock %}
You have forgotten to pass POST method you are using GET.
{% extends 'partials/base.html' %}
{% block title %}Products Edit Page{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row my-4">
<div class="col-md-6 offset-md-3 p-3 bg-white">
<h3>Edit Item</h3>
<hr>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-info" type="submit" value="Confirm">
</form>
</div>
</div>
{% endblock %}

How to make a forum like tag system for images in Django

I am trying to make a educational website using Django where anyone can create posts. Now in those posts I want to provide links to images in a tag so that it shows up in the post. For example something similar to the html img tag will do.
My Post creation view:
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content', 'display', 'category']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def cat_on_all_pages(request):
return {'cat': Category.objects.all()}
My html template for post creation (I use crispy forms here):
{% extends "blog/base.html" %}
{% block title %}Submit a Course{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Submit or Edit a Course</legend>
{{form|crispy}}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}

Django form FileField error 'This Field is required'

I am receiving a This field is required error using a form view that django is generating.
I have a Scan model that looks like:
class Scan(models.Model):
device = models.ForeignKey(Device, null=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField('Created', auto_now=True)
data = models.FileField(upload_to='uploads/')
def __str__(self):
return str("{}-{}".format(self.device, self.created_at))
I have a CreateView defined:
class ScanCreate(LoginRequiredMixin, CreateView):
model = Scan
fields = '__all__'
My url route is
urlpatterns = [
...
path('scan/create/', views.ScanCreate.as_view(), name='scan-create'),
...
]
and finally a scan_form.html template
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
On picking a file to upload and submitting the form, I get the 'This field is required.' error and the request fails:
The file has been selected for upload so why would django report field is required?
The main problem in you code is that you are not using enctype="multipart/form-data" in your form, so when the request is sent to the server, it does not have the file in the request.FILES collection.
you have to write the html code for your form like this:
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
and ensure that the action is pointing to the correct URL.
finally, this is the documentation for file uploads: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/

Why is my Update URL link kicking me to the CreateNew html view

so this is a tag on from my previous stackoverflow post:
Django updateView saving another instance instead of updating
and i think i've narrowed it down. Whats happening is that when i click on the link to update my view, it sends me to the "create new" page. my problem is that I cant figure out why its doing that.
Any and all help is appreciated.
here is the code:
question_form.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Create New Question</h4>
<form method="POST" action="{% url 'questions:create' %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Post" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_update.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'questions:update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_detail.html
{% block content %}
this is the question detail view
<h3>{{ question.question_html|safe }}</h3>
<h3>{{ question.answer_html|safe }}</h3>
Update Question
{% endblock %}
urls.py
url(r'new/$', views.CreateQuestion.as_view(), name='create'),
url(r'questionupdate/(?P<pk>\d+)/$', views.QuestionUpdate.as_view(), name='update'),
url(r'questiondetail/(?P<pk>\d+)/$', views.QuestionDetail.as_view(), name='single'),
views.py
class CreateQuestion(generic.CreateView):
model = models.Question
form = QuestionForm
fields = ('question', 'answer')
success_url = reverse_lazy('questions:all')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class QuestionDetail(generic.DetailView):
model = models.Question
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
context_object_name = 'question'
From your urls.py the name of update view is only update. You can try only update tag in html file Like
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
I've figured it out. it turns out I was missing the template name part under my Create and update views which directs them to their own html templates:
class CreateQuestion(generic.CreateView):
model = models.Question
form_class = QuestionForm
fields = ('question', 'answer')
template_name = "questions/question_form_create.html"
success_url = reverse_lazy('questions:all')
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
template_name = "questions/question_form_update.html"