Can I add a form in django in HTML - django

I want to add comments form a specific html which has it's separate views and models and I don't want to create a new form.html just to display the form and its views. But I'm stuck. I can add comments manually from the admin page and it's working fine, but it seems that I have to create another url and html file to display the comment form and for users to be able to add comments(btw I'm trying to build a sports related website). Thanks in advance!
My models.py:
class Transfernews(models.Model):
player_name = models.CharField(max_length=255)
player_image = models.CharField(max_length=2083)
player_description = models.CharField(max_length=3000)
date_posted = models.DateTimeField(default=timezone.now)
class Comment(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
transfernews = models.ForeignKey(Transfernews, related_name="comments", on_delete=models.CASCADE)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.transfernews.player_name, self.user.username)
My forms.py :
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body',)
My views.py :
def addcomment(request):
model = Comment
form_class = CommentForm
template_name = 'transfernews.html'
My urls.py:
path('comment/', views.addcomment, name='comment'),
My transfernews.html:
<h2>Comments...</h2>
{% if not transfernew.comments.all %}
No comments Yet...
{% else %}
{% for comment in transfernew.comments.all %}
<strong>
{{ comment.user.username }} - {{ comment.date_added }}
</strong>
<br/>
{{ comment.body }}
<br/><br/>
{% endfor %}
{% endif %}
<hr>
<div>Comment and let us know your thoughts</div>
<form method="POST">
{% csrf_token %}
<div class="bg-alert p-2">
<div class="d-flex flex-row align-items-start"><textarea class="form-control ml-1 shadow-none textarea"></textarea></div>
<div class="mt-2 text-right"><button class="btn btn-primary btn-sm shadow-none" type="submit">
Post comment</button><button class="btn btn-outline-primary btn-sm ml-1 shadow-none" type="button">Cancel</button></div>
</div>
</div>
</form>

You don't have to.
In your HTML, take out the anchor tag, you only need the submit button.
<form method="POST">
{% csrf_token %}
<div class="bg-alert p-2">
<div class="d-flex flex-row align-items-start">{{ form.body }}</div>
<div class="mt-2 text-right"><button class="btn btn-primary btn-sm shadow-none" type="submit">
Post comment</button><button class="btn btn-outline-primary btn-sm ml-1 shadow-none" type="button">Cancel</button></div>
</div>
In your views.py, do this.
def view_that_loads_the_page(request, news_id):
news = Transfernews.objects.get(id=news_id)
form_class = CommentForm(request.POST or None)
if form_class.is_valid():
# save both news and logged in user
form.instance.transfernews = news
form.instance.user = request.user
# save form.
form_class.save()
# returns to the same page
return HttpResponseRedirect(request.path_info)
return render(request, "your_html.html", {"form" : form_class})

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)

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 %}

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 %}

Profile isn't updating or updates aren't showing up in django

I am trying to make a page in django where users can look at their profiles and edit and save the changes, but everytime i click on the save button, nothing happens and when I refresh the page, the information doesn't get updated. What am I doing wrong?
This is my models.py:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,null= True ,on_delete= models.CASCADE)
profile_pic = models.ImageField(null = True, blank= True)
first = models.CharField(max_length=500, null=True)
last = models.CharField(max_length=500, null=True)
email = models.CharField(max_length=500, null=True)
mobile_number = models.IntegerField(null=True)
location = models.CharField(max_length= 500, null= True)
postal = models.IntegerField(null=True)
def __str__(self):
return self.first
This is my forms.py:
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
exclude = ['user']
widgets = {
'profile_pic': forms.FileInput()
}
This is my views.py:
#login_required(login_url='Login')
def Profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILE, instance=profile)
if form.is_valid():
form.save()
return HttpResponseRedirect(reversed('Profile'))
context = {'form': form}
return render(request, 'profile.html', context)
This is my template:
<div class="col-lg middle middle-profile-con">
<div class="img-cir profile-img">
<img src="{{request.user.profile.profile_pic.url}}" alt="" width="100px" height="100px" class="pro-img">
</div>
<form method='POST' action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="">
<p class="my-name-pro">{{request.user.profile.first}}
<p>
<p class="my-email-id-pro">{{request.user.profile.email}} <br> {{form.profile_pic}}</p>
</div>
<div class="">
<div class="pro-fn-div">
<label class="pro-fn-label">First name</label>
<div class="pro-fn-input"> {{form.first}} </div>
</div>
<div class="pro-ln-div">
<label class="pro-fn-label">Last name</label>
<div class="pro-fn-input"> {{form.last}} </div>
</div>
<div class="pro-email-div">
<label class="pro-fn-label">Email ID</label>
<div class="pro-fn-input"> {{form.email}} </div>
</div>
<div class="pro-pn-div">
<label class="pro-fn-label">Phone Number</label>
<div class="pro-fn-input"> {{form.mobile_number}} </div>
</div>
<div class="pro-lo-div">
<label class="pro-fn-label">Location</label>
<div class="pro-fn-input"> {{form.location}} </div>
</div>
<div class="pro-pc-div">
<label class="pro-fn-label">Postal Code</label>
<div class="pro-fn-input"> {{form.postal}} </div>
</div>
<button type="button" name="Update Information" class="btn btn-dark btn-sm pro-btn-save">Save Changes</button>
</form>
</div>
I don't understand where I'm going wrong. Do I need to add something in the template? Maybe in the save button or something?
You forgot to register your url so for example :
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('profile/', views.profile, name="profile"),
]
In your template, edit your form
<form method='POST' action="{% url 'profile' %}" enctype="multipart/form-data">
Note that variable in Python are lowercase, following the convention is best

How to add a form in an html page in django

I want to add comments form a specific html which has it's own views and models and I do not want to create a new html file like comment.html which will only display the form and its views. I want users to be able to comment right underneath a post, so that users don't have to click a button such as "add comment" which will take them to a new page with the "comment.form" and then they can comment. Basically want a page with all transfer news and their respective comments as well as a comment-form under the old comment. But I'm stuck. I can add comments manually from the admin page and it's working fine, but it seems that I have to create another url and html file to display the comment form and for users to be able to add comments(btw I'm trying to build a sports related website). Thanks in advance!
My models.py:
class Transfernews(models.Model):
player_name = models.CharField(max_length=255)
player_image = models.CharField(max_length=2083)
player_description = models.CharField(max_length=3000)
date_posted = models.DateTimeField(default=timezone.now)
class Comment(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
transfernews = models.ForeignKey(Transfernews, related_name="comments", on_delete=models.CASCADE)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.transfernews.player_name, self.user.username)
My forms.py :
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body', 'transfernews')
My views.py :
def addcomment(request):
model = Comment
form_class = CommentForm
template_name = 'transfernews.html'
def transfer_targets(request):
transfernews = Transfernews.objects.all()
form = CommentForm(request.POST or None)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.user = request.user
new_comment.save()
return redirect('transfernews/')
return render(request, 'transfernews.html', {'transfernews': transfernews})
My urls.py:
path('transfernews/', views.transfer_targets, name='transfernews'),
My transfernews.html:
<h2>Comments...</h2>
{% if not transfernew.comments.all %}
No comments Yet...
{% else %}
{% for comment in transfernew.comments.all %}
<strong>
{{ comment.user.username }} - {{ comment.date_added }}
</strong>
<br/>
{{ comment.body }}
<br/><br/>
{% endfor %}
{% endif %}
<hr>
<div>Comment and let us know your thoughts</div>
<form method="POST">
{% csrf_token %}
<input type="hidden" value="{{ transfernew.id}}">
<div class="bg-alert p-2">
<div class="d-flex flex-row align-items-start"><textarea class="form-control ml-1 shadow-none textarea"></textarea></div>
<div class="mt-2 text-right"><button class="btn btn-primary btn-sm shadow-none" type="submit">
Post comment</button><button class="btn btn-outline-primary btn-sm ml-1 shadow-none" type="button">Cancel</button></div>
</div>
</div>
</form>
Here's how you can do it :
First, add a field in your CommentForm :
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body', 'transfernews')
Then in your template, you can set an hidden input in the form to link the comment to the transfernews :
{% if form.errors %}
<p>There are errors in your form :</p>
<ul>{{ form.errors }}</ul>
{% endif %}
<form method="POST">
{% csrf_token %}
{# Add this next line #}
<input type="hidden" value="{{ transfernew.id}}">
<div class="bg-alert p-2">
<div class="d-flex flex-row align-items-start">
<textarea class="form-control ml-1 shadow-none textarea" name="body"></textarea>
</div>
<div class="mt-2 text-right">
<button class="btn btn-primary btn-sm shadow-none" type="submit">Post comment</button>
<button class="btn btn-outline-primary btn-sm ml-1 shadow-none" type="button">Cancel</button>
</div>
</div>
</form>
Then in your view :
def transfer_targets(request):
transfernews = Transfernews.objects.all()
form = CommentForm(request.POST or None)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.user = request.user
new_comment.save()
return redirect('transfernews')
return render(request, 'transfernews.html', {
'transfernews': transfernews,
'form': form
})