Edit item within views in Django - 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 %}

Related

Django reference multiple image in template

Hi I am letting the user upload multiple images per project but so far the images are not displayed. In projects.html all projects should be displayed and the title and the describtion work so far. But the main-image doesn´t show up. In single-project all images should be displayed.
What do I have to change in my models.py?
Thanks in forward
models.py
class Project(models.Model):
title = models.CharField(max_length=200)
describtion = models.TextField(null=True, blank=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
class ProjectImage(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
featured_images = models.FileField()
forms.py
class ProjectForm(ModelForm):
featured_images = forms.ImageField(widget=ClearableFileInput(attrs={'multiple':True}))
class Meta:
model = Project
fields = ['title', 'describtion', 'featured_images']
views.py
def createProject(request):
form = ProjectForm()
if request.method == 'POST':
form = ProjectForm(request.POST)
images = request.FILES.getlist('image')
if form.is_valid():
project = form.save()
for i in images:
ProjectImage(project=project, image=i).save()
context = {'form':form}
return render(request, 'projects/project_form.html', context)
def projects(request):
projects = Project.objects.all()
context = {"projects":projects}
return render(request, 'projects/projects.html', context)
def project(request, pk):
projectObj = Project.objects.get(id=pk)
return render(request, 'projects/single-project.html', {'project':projectObj})
projects.html
{% for project in projects %}
<div class="column">
<div class="card project">
<a href="{% url 'project' project.id %}" class="project">
<img class="project__thumbnail" src="{{project.featured_images.url}}" alt="project thumbnail" />
<div class="card__body">
<h3 class="project__title">{{project.title}}</h3>
<h3 class="project__title">{{project.price}} €</h3>
</div>
</a>
</div>
</div>
{% endfor %}
single-project.html
<h3 class="project__title">{{project.title}}</h3>
<h3 class="project__title">{{project.price}} €</h3>
<h3 class="singleProject__subtitle">Infos zum Produkt</h3>
{{project.describtion}}
project_form.html
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form__field">
<label for="formInput#text">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<input class="btn btn--sub btn--lg my-md" type="submit" value="Submit" />
</form>
To access the images of a project, you need to use the related manager in your templates:
projects.html
{% for project in projects %}
<div class="column">
<div class="card project">
<a href="{% url 'project' project.id %}" class="project">
<img class="project__thumbnail" src="{{project.projectimage_set.all.0.featured_images.url}}" alt="project thumbnail" />
<div class="card__body">
<h3 class="project__title">{{project.title}}</h3>
<h3 class="project__title">{{project.price}} €</h3>
</div>
</a>
</div>
</div>
{% endfor %}
I assumed that by "main-image" you mean the first image of the project.
single-project.html
<h3 class="project__title">{{project.title}}</h3>
<h3 class="project__title">{{project.price}} €</h3>
<h3 class="singleProject__subtitle">Infos zum Produkt</h3>
{{project.describtion}}
{% for projectimage in project.projectimage_set.all %}
<img src="{{projectimage.featured_images.url}}"/>
{% endfor %}
To avoid the N+1 query problem, you can also change the query in your view:
views.py
def projects(request):
projects = Project.objects.all().prefetch_related('projectimage_set')
context = {"projects":projects}
return render(request, 'projects/projects.html', context)

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>

I want to make reply to comments feature in Django

I have a simple project and I added a comment feature there. Now I want to add comment reply feature. When I write and send the answer, it registers to sql but I cannot show it on the frontend.
models.py
class Comments(models.Model):
comment_author = models.ForeignKey(ArticleForm, on_delete=models.CASCADE, related_name='comments')
commenter_name = models.ForeignKey(User, on_delete=models.CASCADE)
comment_content = models.TextField()
commented_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "'{}' commented by '{}'".format(self.comment_content, self.commenter_name)
class Meta:
ordering = ['-commented_date']
class ReplyComment(models.Model):
reply_comment = models.ForeignKey(Comments, on_delete=models.CASCADE, related_name='replies')
replier_name = models.ForeignKey(User, on_delete=models.CASCADE)
reply_content = models.TextField()
replied_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "'{}' replied with '{}' to '{}'".format(self.replier_name,self.reply_content, self.reply_comment)
views.py
def detail(request,id):
article = get_object_or_404(ArticleForm,id=id)
comments = article.comments.all()
return render(request, 'detail.html', {'article': article, 'comments': comments})
def replyComment(request,id):
comments = Comments.objects.get(id=id)
if request.method == 'POST':
replier_name = request.user
reply_content = request.POST.get('reply_content')
newReply = ReplyComment(replier_name=replier_name, reply_content=reply_content)
newReply.reply_comment = comments
newReply.save()
messages.success(request, 'Comment replied!')
return redirect('index')
detail.html
<div class="container">
<a type="text" data-toggle="collapse" data-target="#reply{{comment.id}}" style="float: right;" href="">Reply</a><br>
{% if replies %}
{% for reply in replies %}
<div>
<div class="fw-bold"><small><b>Name</b></small></div>
<div style="font-size: 10px;">date</div>
<small>Reply comment</small><br>
</div>
{% endfor %}
{% endif %}
<div id="reply{{comment.id}}" class="collapse in">
<form method="post" action="/article/reply/{{comment.id}}">
{% csrf_token %}
<input name="replier_name" class="form-control form-control-sm" type="hidden">
<input name="reply_content" class="form-control form-control-lg" type="text" placeholder="Reply comment">
<button type="submit" class="btn btn-primary" style="float: right; margin-top: 5px;">Reply</button>
</form>
</div>
What I'm trying to do is pull the responses from the sql and show them below the comment
I will be glad if you can tell me a solution suitable for my codes. Thanks
Perhaps this will work:
{% for comment in comments %}
<div>{{ comment }}</div>
{% for reply in comment.replycomment_set.all %}
<div>
<div class="fw-bold"><small><b>Name {{ reply.replier_name }}</b></small></div>
<div style="font-size: 10px;">date {{ reply.replied_date }}</div>
<small>Reply comment {{ reply.content }}</small><br>
</div>
{% endfor %}
{% endfor %}

Reverse for 'profile_update' with arguments '(1,)' not found. Issue

I have a base url link to access a profile edtting screen but it seems to break my application.
Ive tried so many things that i am getting confused by the different views. I was able to get the form appearing previously but have somehow broken it.
from my base.html(if i remove this line the app start to work again). Im not sure about this user.id parameter im passing in this - is it needed?
<li class="nav-item">
<a class="nav-link" href="{% url 'accounts:profile_update' user.id %}">Edit Profile</a>
</li>
my urls file:
path('profile/edit/', views.ProfileCreate.as_view(), name='profile_update'),
my model:
class Profile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='userprofile')
houseNumber = models.CharField(max_length=150, default='')
street = models.CharField(max_length=150, default='')
suberb = models.CharField(max_length=150, default='')
city = models.CharField(max_length=150, default='')
phone = models.CharField(max_length=150, default='')
def __unicode__(self):
return self.user.get_full_name()
def __str__(self):
return self.user
def get_absolute_url(self):
return reverse('account:profile', kwargs=[self.pk])
my form:
class ProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
class Meta:
model = Profile
fields = ['user', 'houseNumber', 'street', 'suberb', 'city', 'phone']
the html for the form:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<div class="container">
<form enctype="multipart/form-data" action="{% url 'accounts:profile_update' %}" method="post" novalidate>
{% csrf_token %}
{{ form|crispy }}
<input name="Submit" type="submit" class="btn btn-success" value="Save"></input>
</form>
<p></p>
</div>
{% endblock %}
Apologies if this question is similar to a few others Ive asked but i just had to restart with this form using a different approach because it just wasnt working properly previously.
According to you url, you don't need to pass user.id through update_profile. So please change the code to:
<a class="nav-link" href="{% url 'accounts:profile_update' %}">Edit Profile</a>

Uploading multiple images in Django with django-multiupload library

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.