'bytes' object has no attribute '_committed' - django

I will create multi image add page. But the following error occurs. Could your help me? I think mistake in views.py. I'm not sure.
Note : It's frustrating that Stackoverflow asks for a long explanation.
error:
AttributeError at /en/projects/multiimageadd/10/
'bytes' object has no attribute '_committed'
#login_required
#permission_required('is_superuser')
def MultiImageAdd(request, id):
blog = BlogModel.objects.filter(id=id).first()
if request.method == 'POST':
images = request.FILES['images']
for image in images:
Images.objects.create(project=project, image=image)
return redirect("home")
return render(request,"multiImage.html")
<div class="container-fluid">
<div class="row">
<div class="col-sm-12">
<div class="card">
<div class="card-header">
</div>
<div class="card-body">
<form class="needs-validation" method="POST" action="" enctype="multipart/form-data"
novalidate="">
{% csrf_token %}
<div class="row">
<div class="col-sm-12">
<div class="form-group row">
<label for="id_images" class="col-xl-3 col-md-4">Images:</label>
<span class="form-control col-md-8">
<input required type="file" name="images" id="id_images" multiple>
</span>
</div>
</div>
</div>
<div class="pull-right">
<button class="btn btn-primary" type="submit">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
models.py
class Images(models.Model):
blog = models.ForeignKey(BlogModel, related_name='blogmodel', on_delete=models.CASCADE, blank=True,null=True)
image = models.ImageField(blank=False, null=True)

You should enumerate over the file handlers, so obtain the handlers with .getlist(…) [Django-doc]:
images = request.FILES.getlist('images')
for image in images:
Images.objects.create(project=project, image=image)

Related

Image not getting uploaded in Django

I tried to save a record using two different methods but both are not working.
Django Form
Models (create method)
1 I have created a ModelForm
class ProductForm(ModelForm):
class Meta:
model= ProductDetails
fields= ("name","category","subcategory","price","mrp","product_details","main_img","img1","img2","img3")
labels={
"name":"Product Name",
"product_details":"Description",
"category":"Category",
"subcategory":"Sub-Category",
"price":"Price",
"mrp":"MRP",
"main_img":"Main Image",
"img1":"Image 1",
"img2":"Image 2",
"img3":"Image 3",
}
widgets = {
'name':forms.TextInput(attrs={'class':'form-control validate',}),
'product_details':forms.TextInput(attrs={'class':'form-control validate',}),
'category':forms.TextInput(attrs={'class':'custom-select tm-select-accounts',}),
'subcategory':forms.TextInput(attrs={'class':'custom-select tm-select-accounts',}),
'price':forms.TextInput(attrs={'class':'form-control validate',}),
'mrp':forms.TextInput(attrs={'class':'form-control validate',}),
'main_img':forms.FileInput(attrs={'class':'btn btn-primary btn-block mx-auto',}),
'img1':forms.FileInput(attrs={'class':'btn btn-primary btn-block mx-auto',}),
'img2':forms.FileInput(attrs={'class':'btn btn-primary btn-block mx-auto',}),
'img3':forms.FileInput(attrs={'class':'btn btn-primary btn-block mx-auto',}),
}
Models File
# For Product details
class ProductDetails(models.Model):
name= models.CharField(max_length=100)
price= models.FloatField()
mrp= models.FloatField()
main_img = models.ImageField(upload_to='product_img')
img1 = models.ImageField(upload_to='product_img')
img2 = models.ImageField(upload_to='product_img')
img3 = models.ImageField(upload_to='product_img')
category = models.ForeignKey(Category, related_name='produits', on_delete=models.CASCADE)
subcategory = models.ForeignKey(SubCategory, related_name='produits', on_delete=models.CASCADE)
product_details = RichTextField(blank=True, null=True)
trending = models.BooleanField(default=False)
def __str__(self):
return self.name
Method 1
Save record using form.save()
getting Form validation error
I have tried by removing main_img,img1,img2,img3 from all place (Forms.py, template, views,py). Then there is not validation error and record is getting saved successfully.
The validation error is just because of some issue with the image uploading
print(form.errors)= <ul class="errorlist"><li>main_img<ul class="errorlist"><li>This field is required.</li></ul></li><li>img1<ul class="errorlist"><li>This field is required.</li></ul></li><li>img2<ul class="errorlist"><li>This field is required.</li></ul></li><li>img3<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
def add_product(request):
if request.method == "POST":
form = ProductForm(request.POST or None, request.FILES or None)
print(form.errors )
if form.is_valid():
category_id = request.POST.get('category')
subcategory_id = request.POST.get('subcategory')
category= Category.objects.get(id=int(category_id))
subcategory= SubCategory.objects.get(id=int(subcategory_id))
form.category = category
form.subcategory = subcategory
form.save()
return redirect("/dashboard/products")
form = ProductForm()
categories=Category.objects.all()
subcategories=SubCategory.objects.all()
return render(request, "01-add-product.html", "form":form,"categories":categories,"subcategories":subcategories})
Method 2
Tried Saving records using models.save()
The record is getting saved but image is not getting uploaded to the media folder
On saving record from Django-admin the image is getting uploaded to proper place i.e. /media.product_img/...
But From this outside HTML its showing the file name in Django-admin but the file is not available in media folder
I already added urlpattern + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) in my project/urls.py.
Also tried adding the same in urls.py of this app
Note = I have mentioned upload_to=product_img in my model (this may be important to know)
def add_product(request):
if request.method == "POST":
name = request.POST['name']
product_details = request.POST['product_details']
category_id = request.POST.get('category')
subcategory_id = request.POST.get('subcategory')
category= Category.objects.get(id=int(category_id))
subcategory= SubCategory.objects.get(id=int(subcategory_id))
price = request.POST['price']
mrp = request.POST['mrp']
main_img = request.POST['main_img']
img1 = request.POST['img1']
img2 = request.POST['img2']
img3 = request.POST['img3']
product = ProductDetails.objects.create(name=name,product_details=product_details,category=category,subcategory=subcategory,price=price,mrp=mrp,main_img=main_img,img1=img1,img2=img2,img3=img3)
product.save()
Here is my template
{% extends '01-admin-base.html' %}
{% load static %}
{% block content %}
<div class="container tm-mt-big tm-mb-big">
<div class="row">
<div class="col-xl-9 col-lg-10 col-md-12 col-sm-12 mx-auto">
<div class="tm-bg-primary-dark tm-block tm-block-h-auto">
<div class="row">
<div class="col-12">
<h2 class="tm-block-title d-inline-block">Add Product</h2>
</div>
</div>
<div class="row tm-edit-product-row">
<div class="col-xl-6 col-lg-6 col-md-12">
<form action="" method="post" class="tm-edit-product-form">
{% csrf_token %}
{{form.media}}
<div class="form-group mb-3">
<label
for="name"
>Product Name
</label>
{{form.name}}
</div>
<div class="form-group mb-3">
<label
for="category"
>Category</label
>
<select
class="custom-select tm-select-accounts"
id="category" name="category"
>
<option selected>Select category</option>
{% for category in categories %}
<option value="{{category.id}}">{{category.name}}</option>
{% endfor %}
</select>
</div>
<div class="form-group mb-3">
<label
for="subcategory"
>Sub Category</label
>
<select
class="custom-select tm-select-accounts"
id="subcategory" name="subcategory"
>
<option selected>Select sub-category</option>
{% for subcategory in subcategories %}
<option value="{{subcategory.id}}">{{subcategory.name}}</option>
{% endfor %}
</select>
</div>
<div class="row">
<div class="form-group mb-3 col-xs-12 col-sm-6">
<label
for="price"
>Price
</label>
{{form.price}}
</div>
<div class="form-group mb-3 col-xs-12 col-sm-6">
<label
for="mrp"
>MRP
</label>
{{form.mrp}}
</div>
</div>
<div class="form-group mb-3">
<label
for="description"
>Description</label
>
{{form.product_details}}
</div>
</div>
<div class="col-xl-6 col-lg-6 col-md-12 mx-auto mb-4">
<div class="custom-file mt-3 mb-3">
<label>Main Image</label>
{{form.main_img}}
</div>
<br><br>
<label>Images</label>
<div class="custom-file mt-3 mb-3">
{{form.img1}}
</div>
<div class="custom-file mt-3 mb-3">
{{form.img2}}
</div>
<div class="custom-file mt-3 mb-3">
{{form.img3}}
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary btn-block text-uppercase">Add Product Now</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
Please help me to get solution for this.
You need to add enctype="multipart/form-data"> in Html form so:
<form action="/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label for="fname">First name:</label>
<input type="text" id="fname" name="fname"><br><br>
<label for="lname">Last name:</label>
<input type="text" id="lname" name="lname"><br><br>
<input type="submit" value="Submit">
</form>

django returns MultiValueDictKeyError at / 'q'

django returns MultiValueDictKeyError at /
'q' in my dashboard template when I'm trying to add search functionality into my app. I want when a user type something on the search input to return the value that user searched for. but i endup getting an error when i try to do it myself.
MultiValueDictKeyError at /
'q'
def dashboard(request):
photos = Photo.objects.all()
query = request.GET['q']
card_list = Photo.objects.filter(category__contains=query)
context = {'photos': photos, 'card_list':card_list}
return render(request, 'dashboard.html', context)
<div class="container">
<div class="row justify-content-center">
<form action="" method="GET">
<input type="text" name="q" class="form-control">
<br>
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
<br>
<div class="container">
<div class="row justify-content-center">
{% for photo in photos reversed %}
<div class="col-md-4">
<div class="card my-2">
<img class="image-thumbail" src="{{photo.image.url}}" alt="Card
image cap">
<div class="card-body">
<h2 style="color: yellowgreen; font-family: Arial, Helvetica,
sans-serif;">
{{photo.user.username.upper}}
</h2>
<br>
<h3>{{photo.category}}</h3>
<h4>{{photo.price}}</h4>
</div>
<a href="{% url 'Photo-view' photo.id %}" class="btn btn-warning btn-
sm m-1">Buy Now</a>
</div>
</div>
{% empty %}
<h3>No Files...</h3>
{% endfor %}
</div>
</div>
try this
query = request.GET['q']
query = request.GET.get('q', '') # use get to access the q
The get() method returns the value of the item with the specified key.

How to render error or validation messages to ModelForm in 2022

I've spent several hours researching on the internet, especially the official Django documentation, but still it is not clear to me which is the best option in 2022 (since almost all questions I read on SO are > 6 yo)
and there are diverse opinions on whether crispy forms is better or not.
Is still crispy forms a recommended option?
How can I (and what is the most recommended way to) get the typical validation error messages?
Like: "this field is mandatory" or "this input accepts numbers only"? I've seen some Django pages using those default messages but I don't know how to show them in my ModelForm fields.
Lets say I have the following model:
class Project(models.Model):
project_name = models.CharField(max_length=250, null=False, blank=False)
status = models.CharField(
max_length=250,
null=True,
blank=True,
default=PROJECT_STATUS_DEFAULT,
choices=PROJECT_STATUS,
)
creation_date = models.DateField(max_length=250, null=False, blank=False)
project_code = models.IntegerField(null=True, blank=True)
notes = models.CharField(max_length=250, null=True, blank=True)
And for the Project model I have the following ModelForm:
class CreateNewProjectForm(ModelForm):
creation_date = forms.DateField(widget=forms.DateInput(format = '%d/%m/%Y'), input_formats=settings.DATE_INPUT_FORMATS) #UK Date format
class Meta:
model = Project
fields = '__all__'
The view, when I try to create a new object Project:
def add_new_project(request):
context = {}
if request.method == 'POST':
form = CreateNewProjectForm(request.POST)
if form.is_valid():
form.save()
return redirect('project_page')
else:
print (form.errors)
form = CreateNewProjectForm()
context['form'] = form
return render(request, 'new_project.html', context)
HTML part:
<div class="card h-100">
<div class="card-header project-page-header">
<h3>Create A New Project</h3>
</div>
<div class="card-body px-0 new-project-card-body">
<div class="cardItem">
<div class="row">
<div class="col">
<div class="row">
<div class="tab-pane fade show active" id="general">
<form id="newProjectForm" method="POST" action="new_project">
{% csrf_token %}
<div class="accordion accordion-flush" id="accordionGeneral">
<div class="accordion-item">
<h2 class="accordion-header" id="general-headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#general-collapseOne" aria-expanded="false" aria-controls="general-collapseOne">
Details
</button>
</h2>
<div id="general-collapseOne" class="accordion-collapse collapse show" aria-labelledby="general-headingOne" data-bs-parent="#accordionGeneral">
<div class="accordion-body">
<div class="row">
<div class="col-5">
<ul class="list-unstyled">
<li class="mt-3">
<div class="row">
<div class="col-sm ph-tabs-field-label">
Project Name
</div>
<div class="col-sm">
<input type="text" name="project_name" class="form-control" aria-label="Project Name">
</div>
</div>
</li>
<li class="mt-3">
<div class="row">
<div class="col-sm ph-tabs-field-label">
Status
</div>
<div class="col-sm">
<select name="status" class="selectpicker show-tick w-100" aria-label="Status">
{% for status in project_status %}
{% if forloop.first %}
<option value="{{ status.id }}" selected>{{ status.text }}</option>
{% else %}
<option value="{{ status.id }}">{{ status.text }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
</li>
<li class="mt-3">
<div class="row">
<div class="col-sm ph-tabs-field-label">
Creation Date
</div>
<div class="col-sm">
<input type="text" name="creation_date" class="form-control">
</div>
</div>
</li>
<li class="mt-3">
<div class="row">
<div class="col-sm ph-tabs-field-label">
Project Code
</div>
<div class="col-sm">
<input type="text" name="project_code" class="form-control">
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="general-headingThree">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#general-collapseThree" aria-expanded="false" aria-controls="general-collapseThree">
Note
</button>
</h2>
<div id="general-collapseThree" class="accordion-collapse collapse" aria-labelledby="general-headingThree" data-bs-parent="#accordionGeneral">
<div class="accordion-body"><textarea name="notes" class="form-control" rows="7"></textarea></div>
</div>
</div>
<button type="submit" id="projectEditBtn" form="newProjectForm" class="btn btn-info rounded-0">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I saw solutions like this, but the problem is that my form fields are spread over different accordions, I can't use something like {% if form.errors %}, I need something more specific for each field.
First update your views like this
def add_new_project(request):
context = {}
if request.method == 'POST':
form = CreateNewProjectForm(request.POST)
if form.is_valid():
form.save()
return redirect('project_page')
else:
print (form.errors)
context['form'] = form
return render(request, 'new_project.html', context)
context['form'] = CreateNewProjectForm()
return render(request, 'new_project.html', context)
You can specify error for each field like this
{% if form.field_name.errors %}
{{ form.field_name.errors }}
{% endif %}

request.GET.get() returns None all the time - django

I have these two models :
class Payment(models.Model):
admin = models.ForeignKey(User,on_delete=models.PROTECT)
client_seller = models.ForeignKey(ClientCompany,on_delete=models.PROTECT,blank=True)
next_payment = models.OneToOneField(NextPayment,blank=True,null=True,related_name='next_payments',on_delete=models.PROTECT)
#others
class NextPayment(models.Model):
next_payment = models.DateTimeField()
status = models.BooleanField(default=True)
I want to create NextPayment instance before Payment instance will be create , and assign the NextPayment object to Payment > next_payment field ! here is my views.py
#login_required
def create_payment(request):
main_form = PaymentForm()
next_paymentform = NextPaymentForm()
next_payment= request.GET.get('next_payment')
print(next_payment)
if request.method == 'POST' and request.is_ajax():
main_form = PaymentForm(request.POST)
next_paymentform = NextPaymentForm(request.POST)
if main_form.is_valid():
main_obj = main_form.save(commit=False)
main_obj.admin = request.user
if next_payment:
date_next = next_paymentform(next_payment=next_payment)
#date_next = NextPayment(next_payment=next_payment,status=True) also tried this
date_next.save()
main_obj.next_payment= date_next
main_obj.save()
else:
main_obj.save()
data = {
'id':main_obj.id
}
return JsonResponse({'success':True,'data':data})
else:
return JsonResponse({'success':False,'error_msg':main_form.errors,'next_paymentform':next_paymentform.errors})
return render(request,'payments/pay.html',{'main_form':main_form,'next_paymentform':next_paymentform})
my forms.py
class NextPaymentForm(forms.ModelForm):
next_payment = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'],widget=forms.DateTimeInput(attrs={'type':'datetime-local','class':'form-control'}),required=False)
class Meta:
model = NextPayment
fields = ['next_payment']
class PaymentForm(forms.ModelForm):
class Meta:
model = Payment
fields = ['client_seller','type_of_payment','price','note']
here is my template
<form action="" method="POST" id="create-payment-form">{% csrf_token %}
<div class="row">
<div class="col-md-6">
<div class="form-group">
<i class="fas fa-user-check"></i>
<label>name </label>
{{ main_form.client_seller | add_class:'form-control' | append_attr:'onchange:currentPaymentBalance();' }}
</div>
</div>
<!-- /.col -->
<div class="col-md-6">
<div class="form-group">
<i class="fas fa-money-check-alt"></i>
<label>number</label>
<input type="number" class="form-control" disabled id="balance_client">
</div>
<!-- /.form-group -->
</div>
<div class="col-md-6">
<div class="form-group">
<i class="far fa-handshake"></i>
<label> type</label>
{{ main_form.type_of_payment | add_class:'form-control' }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<i class="fas fa-money-check-edit-alt"></i>
<label> price</label>
{{ main_form.price }}
</div>
</div>
<div class="col-md-12 col-12">
<div class="form-group text-center ">
<i class="far fa-comment-dots"></i>
<label class="">note</label>
{{ main_form.note | add_class:'form-control' }}
</div>
</div>
<div class="col-md-6 justify-content-center">
<div class="form-group">
<i class="fas fa-quote-right"></i>
<label> next payment</label>
{{ next_paymentform.next_payment }}
</div>
</div>
<!-- /.col -->
</div>
<!-- /.row -->
<div class="card-footer">
<div class="row justify-content-center">
<button type="submit" class="btn btn-lg btn-success">زیادکردن</button>
</div>
</div>
</form>
next_payment prints None! but it wasn't None
but doesn't work, and only saves the main form! I need to check if the next_payment exists then create an instance of NextPayment and assign that new instance to the Payment model?
any idea is much appreciated.
thank you in advance...
Since your form is sending a POST request you have to change
next_payment= request.GET.get('next_payment')
to
next_payment= request.POST.get('next_payment')

How is it possible to get data from one form that has multiple textareas in Django

I'd like to get data from one form that has multiple textareas inside , In my views: 'compare_ingredients' I've tried requesting data from my form id 'compareform' also the textarea id 'ingredients', but when I enter something into one texture and click on submit it comes back as 'None' when I print. Here is my html and views:
html :
<div class="container-fluid">
<h4>Please enter in your ingredients:</h4>
<h6>(Seperate each item by comma)</h6>
<br>
<button class="add_item">Add Item</button>
<br>
<div class="row row-cols-1 row-cols-md-2 mx-auto">
<form action="{% url 'compare_ingredients' %}" method="POST" name="compareform" id="compare">
{% csrf_token %}
<br>
<button type="submit" class="btn btn-info sub_btn">Submit</button>
<button type="submit" class="btn btn-secondary back_button">
Back
</button>
<br>
<br>
<div class="row form_row">
<div class="col mb-4">
<h5>Item 1</h5>
<div class="card form_card">
<div class="card-body compare_cardbody">
<textarea name="ingredients1" id="ingredients" cols="30" rows="10" form="compareform"></textarea>
</div>
</div>
</div>
<div class="col mb-4">
<h5>Item 2</h5>
<div class="card form_card">
<div class="card-body compare_cardbody">
<textarea name="ingredients2" id="ingredients" cols="30" rows="10" form="compareform"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
views.py:
def compare_ingredients(request):
if request.method == "POST":
ingredients = request.POST.get('compareform')
print(ingredients)
return render(request, 'result/compare.html')
ok, I figured it out , the problem was in the html textarea I had the name of the form as 'compareform' when it should have been 'compare' :
<textarea name="ingredients2" id="ingredients" cols="30" rows="10" form="compare"></textarea>
then in my views I did:
ingredients1 = request.POST.get('ingredients1')