I am adding a functionality in my website, where users can like posts.
I have successfully done this, however I am having trouble adding one functionality.
This is text within a button depending on whether a post is liked or not.
Right now the button stays the same no matter if the post is liked or not.
models.py
class Post(models.Model):
file = models.ImageField(upload_to='images/')
summary = models.TextField(max_length=600)
pub_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(User, through='Like', related_name='likes')
def __str__(self):
return self.user.username
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def summary_pretty(self):
return self.summary[:50]
#property
def total_likes(self):
return self.likes.count()
class Like(models.Model):
status = models.BooleanField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
views.py
def likepost(request, post_id):
if request.method == 'POST':
post = get_object_or_404(Post, pk=post_id)
user = request.user
if post.likes.filter(id=user.id).exists():
post.likes.remove(user)
return redirect('home')
else:
like = Like()
like.post = post
like.user = user
like.status = True
like.save()
post.likes.add(user)
return redirect('home')
my template:
{% if post.likes.status == True %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Unlike {{ post.total_likes }} </button>
{% else %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Like {{ post.total_likes }} </button>
{% endif %}
EDIT - HOME VIEW:
#login_required(login_url="/login")
def home(request):
posts = Post.objects.all()
return render(request, 'posts/home.html', {'posts': posts})
EDIT 2:
{% extends 'accounts/base.html' %}
{% block content %}
{% load static %}
{% for post in posts.all %}
<div class="container pl-5">
<div class="row pt-3">
<img src="{% static 'grey.jpg' %}" width="600px" height="60px">
<div class="pt-3 pl-5" style="position: absolute;"> <b> {{ post.user.username }} </b> </div>
</div>
<br>
<div class="card" style="width: 600px; bottom: 24px; right: 15px;">
<img src="{{ post.file.url }}" width="599px">
</div>
<br>
<div class="card" style="width: 600px; bottom: 50px; right: 15px;"> <img src="{% static 'grey.jpg' %}" width="600px" height="150px"> </div>
<div class="col-6" style="bottom:145px; left: 5px;">
<div style="position: absolute;"> <b> {{ post.user.username }} </b> {{ post.summary_pretty }}</div>
</div>
{% for like in post.likes.all %}
{{like.username}}
{% endfor %}
{% if like.status %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Unlike {{ post.total_likes }} </button>
{% else %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Like {{ post.total_likes }} </button>
{% endif %}
<form id="likepost{{ post.id }}" method="POST" action="{% url 'likepost' post.id %}">
{% csrf_token%}
<input type="hidden">
</form>
</div>
<br>
<br>
<br>
{% endfor %}
{% endblock %}
In your model you have defined likes as a ManyToManyField field:
class Post(models.Model):
likes = models.ManyToManyField(User, through='Like', related_name='likes')
But in your template you are trying to get a single boolean value from many likes:
{% if post.likes.status == True %}
post.likes will return multiple objects. You need to instead get the like based on the user.
EDIT:
One way you could get the like status is by doing the following in your view:
context['like'] = Like.objects.get(post=post, user=request.user)
Then in your template:
{% if like.status == True %}
Related
I want to save my form in database, but save() doesn't work. When I do this, error wasn't showing. At the start, I think problem was in database, but it isn't
views.py
def comments(request):
comments = Comment.objects.all()
form = CommentForm()
context = {"comments": comments, "form": form}
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.avtor = request.user
comment.save()
return HttpResponseRedirect(reverse('comment'))
else:
context["form"] = form
return render(request, "home/comments.html", context)
else:
return render(request, "home/comments.html", context)
And models. So, I think problem yet in views.py. I bad know how function save() is working.
models.py
class Comment(models.Model):
Text = models.TextField(verbose_name='Text')
date = models.DateTimeField(default=timezone.now, verbose_name='date')
avtor = models.ForeignKey(User, verbose_name='avtor', on_delete=models.CASCADE)
def __str__(self):
return 'Comment {} at {}'.format(self.avtor, self.date)
class Meta:
ordering = ["-id"]
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ("Text",)
At the last, I want to save avtor, text and Date. Help me please.
<div class="container" style="min-height: 520px;">
<form class="text-light formGroupComm" action="/" method="post">
{% csrf_token %}
{{ form }}
<br>
<button style="width: 6%!important;" class="btn btn-warning mb-5 mt-3 mx-auto" type="submit">submit</button>
</form>
<div class="comments text-dark">
{% for comentPost in comments %}
<div class="commentItem bg-warning my-3" style="border-radius: 40px; padding: 20px;">
<div style="border-bottom: 3px solid black;" class="comTitle mx-3 my-3">{{ comentPost.avtor }}</div>
<div style="" class="comText mx-5">{{ comentPost.Text }}</div>
<div style="" class="comDate mx-3 my-5">{{ comentPost.date|date:"F d, Время: h:i" }}</div>
</div>
{% endfor %}
</div>
</div>
The action attribute specifies where to send the form-data when a form is submitted (https://www.w3schools.com/tags/att_form_action.asp).
So when you put the "/" in there, the form will send the data to the home page (represented by / in html). This means that your data doesn't get to the POST section of your def comments(request) method. When the method is not called, the logical outcome is thus that there isn't a new comment added.
This is the correct code:
<div class="container" style="min-height: 520px;">
<form class="text-light formGroupComm" method="post">
{% csrf_token %}
{{ form }}
<br>
<button style="width: 6%!important;" class="btn btn-warning mb-5 mt-3 mx-auto" type="submit">submit</button>
</form>
<div class="comments text-dark">
{% for comentPost in comments %}
<div class="commentItem bg-warning my-3" style="border-radius: 40px; padding: 20px;">
<div style="border-bottom: 3px solid black;" class="comTitle mx-3 my-3">{{ comentPost.avtor }}</div>
<div style="" class="comText mx-5">{{ comentPost.Text }}</div>
<div style="" class="comDate mx-3 my-5">{{ comentPost.date|date:"F d, Время: h:i" }}</div>
</div>
{% endfor %}
</div>
</div>
I think I've tried all the solutions from Internet to allow custom users to edit their profile but I still can't manage to do it.
To illustrate my architecture, I have a profile page on which there is an edit button. This button open a modal form to edit the profile. I think I have to do something with my url (to include pk in it) but I don't understand how : if I use a simple path (without pk) I have this error :
Reverse for 'edit_profile_modal' not found. 'edit_profile_modal' is not a valid view function or pattern name and when I try to add pk I have this one : Reverse for 'edit_profile' with no arguments not found. 1 pattern(s) tried: ['accounts/edit_profile/(?P[0-9]+)$']
Here is my code :
accounts/url.py
urlpatterns = [
...
path('profil/', ProfileView.as_view(), name="profil"),
path('edit_profile/',EditProfileView.as_view(),name="edit_profile"),]
views.py
class EditProfileView(BSModalUpdateView):
model = Account
template_name = 'accounts:edit_profile'
form_class = EditProfileForm
success_message = 'Le profil a été modifié avec succès'
success_url = reverse_lazy('accounts:profil')
profil.html
<!--Modal-->
<script type="text/javascript">
$(document).ready(function() {
$("#edit-profile").modalForm({
formURL: "{% url 'accounts:edit_profile' %}"
});
});
</script>
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
</div>
</div>
</div>
<button id="edit-profile" class="btn btn-primary" type="button" name="button"><a class="nav-link active" href="{% url 'accounts:edit_profile_modal'%}">Editer »</a></button>
edit_profile_modal.html
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Update Account</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div><form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Update Account</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Update</button>
</div>
forms.py
class EditProfileForm(BSModalModelForm):
class Meta:
model = Account
fields = ['email', 'username','prenom','nom','birthday']
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
prenom = models.CharField(max_length=30)
nom = models.CharField(max_length=30)
birthday = models.DateField(auto_now=False, auto_now_add=False, default=now)
objects = MyAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['prenom', 'nom']
description = models.CharField(max_length=50, default='')
birthday = models.DateField(auto_now=False, auto_now_add=False, default=now)
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
def getFirstNameAndName(self):
return self.prenom +" "+self.nom
In your html you have:
href="{% url 'accounts:edit_profile_modal'%}
But in your urls you call it edit_profile
So changing that plus adding the pk would give:
href="{% url 'accounts:edit_profile' pk=object_pk %}
And change your url to:
path('edit_profile/<int:pk>',EditProfileView.as_view(),name="edit_profile")
show Reply button should be specific for different comments . When I press show reply button it opens different replies which dosen't belong to that comment.
views.py
from django.shortcuts import render, HttpResponse, redirect,reverse
from fitness.models import Post, BlogComment
from django.contrib.auth.models import User
from fitness.templatetags import extras
# Create your views here.
def fitness(request):
everypost=Post.objects.all()
context={"everypost":everypost}
return render(request, "fitness/fit.html", context)
def blogfit(request, slug):
post=Post.objects.filter(slug=slug).first()
comments= BlogComment.objects.filter(post=post, parent=None)
replies= BlogComment.objects.filter(post=post).exclude(parent=None)
replyDict={}
for reply in replies:
if reply.parent.sno not in replyDict.keys():
replyDict[reply.parent.sno]=[reply]
else:
replyDict[reply.parent.sno].append(reply)
context={"post":post, 'comments': comments, 'user': request.user, 'replyDict': replyDict}
return render(request, "fitness/blogfit.html", context)
def postComment(request):
if request.method == "POST":
comment=request.POST.get('comment')
user=request.user
postSno =request.POST.get('postSno')
post= Post.objects.get(sno=postSno)
parentSno= request.POST.get('parentSno')
if parentSno=="":
comment=BlogComment(comment= comment, user=user, post=post)
comment.save()
else:
parent= BlogComment.objects.get(sno=parentSno)
comment=BlogComment(comment= comment, user=user, post=post , parent=parent)
comment.save()
return HttpResponse(reverse('fitness:fitness'))
Models.py
from django.db import models
from ckeditor.fields import RichTextField
from django.contrib.auth.models import User
from django.utils.timezone import now
# Create your models here.
class Post(models.Model):
sno=models.AutoField(primary_key=True)
title=models.CharField(max_length=255)
author=models.CharField(max_length=14)
slug=models.CharField(max_length=130)
timeStamp=models.DateTimeField(blank=True)
content=RichTextField(blank=True, null=True)
def __str__(self):
return self.title + " by " + self.author
class BlogComment(models.Model):
sno= models.AutoField(primary_key=True)
comment=models.TextField()
user=models.ForeignKey(User, on_delete=models.CASCADE)
post=models.ForeignKey(Post, on_delete=models.CASCADE)
parent=models.ForeignKey('self',on_delete=models.CASCADE, null=True )
timestamp= models.DateTimeField(default=now)
def __str__(self):
return self.comment[0:13] + "..." + "by" + " " + self.user.username
Html page
<h2 class="blog-post-title">{{post.title}}</h2>
<p class="blog-post-meta">{{post.timeStamp}} by {{post.author}}</p>
<p>{{post.content|safe}}</p>
<hr>
</div>
</div>
</div>
{% if user.is_authenticated %}
<form action="{% url 'fitness:postComment' %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="exampleInputEmail1">Post Comment </label>
<input type="text" class="form-control" name="comment" placeholder="Enter comment here">
</div>
<input type="hidden" name="postSno" value="{{post.sno}}">
<input type="hidden" name="parentSno" value="">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% else %}
Please login to post a comment
{% endif %}
</div>
{% for comment in comments %}
<div class="row my-3">
<div class="col-md-1 ">
<img class="rounded mx-auto d-block w-100 border border-dark p-2" src="http://i9.photobucket.com/albums/a88/creaticode/avatar_1_zps8e1c80cd.jpg" alt="user">
</div>
<div class="col-md-11 ">
<h6 class="comment-name by-author"> {{comment.user.username}} </h6> <span class="badge badge-secondary "></span>
<b> {{comment.comment}} </b> <span class="badge badge-secondary "></span><br>
<button class="btn btn-sm btn-primary" type="button" data-toggle="collapse" data-target="#replyBox{{comment.sno}}" aria-expanded="false" aria-controls="replyBox{{comment.sno}}">
Reply
</button>
<button class="btn btn-sm btn-primary" type="button" onClick="myFunction()" id= "show-hide" >
Show Replies
</button>
<div class="reply mx-0" >
<div class="collapse" id="replyBox{{comment.sno}}">
<div class="card card-body my-2" >
<form action="{% url 'fitness:postComment' %}" method="post">
{% csrf_token %}
<div class="form-group" >
<label for="comment">Post a reply </label>
<input type="text" class="form-control" name="comment" placeholder="Enter comment here">
<input type="hidden" name="parentSno" value="{{comment.sno}}">
</div>
<input type="hidden" name="postSno" value="{{post.sno}}">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<div class="replies bg-danger my-2" id = "replies" >
{% for reply in replyDict|get_val:comment.sno %}
<div class="replies">{{reply}}</div>
<br>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
<!-- Contenedor Principal -->
<script>
function myFunction(){
var x = document.getElementById("replies");
if(x.style.display === "none"){
x.style.display = "block";
}
else{
x.style.display = "none";
}
}
</script>
I think it is a logical error. Can someone help me to find out this error? While everything is working fine but my reply button not working fine.
Change in models.py. update parent in BlogComment (add related_name)
parent=models.ForeignKey('self', on_delete=models.CASCADE, null=True, related_name='replies' )
Change in views.py where you are getting comments
comments= BlogComment.objects.filter(post=post, parent=None).prefetch_related('replies')
You don't need separate query for replies.
In html (Only for replies. Please change as per your requirement)
{% for comment in comments %}
{% for reply in comment.replies.all %}
{{ reply.comment }}
{% endfor %}
{% endfor %}
This will work. Remember related_name=replies
(Sorry for unclear answer. It's closing time in office and I am leaving. Good luck)
In my site I have 2 sections for users. The user posts page and the profile page. The profile page has all their info on it, so username, description, first/last name, etc. And the user posts page has all their posts on it. However, I want to integrate them together somehow.
Here is some of the code.
Here is the view for the User Posts
class UserPostListView(ListView):
model = Post
template_name = 'mainapp/user_posts.html'
context_object_name = 'posts'
def get_queryset(self):
user = get_object_or_404(User,username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-published_date')
As you can see, I am returning the specific users posts.
And now here is my profile view
def view_profile(request,pk=None):
if pk:
user_profile = User.objects.get(pk=pk)
else:
user_profile = request.user
context = {'user':user_profile}
return render(request,'mainapp/profile.html',context)
It returns all the user's info.
Here is the HTML code for both the profile and user posts page
{% block content %}
<div class="profile-page-container">
<div class="profile-page-info">
<div class="profile-page-banner">
<div class="profile-page-banner-background">
<!-- <img src="https://cdn.pixabay.com/photo/2017/08/30/01/05/milky-way-2695569_960_720.jpg" alt="{{ user }}'s Background Image" > -->
</div>
<div class="profile-page-banner-text">
<h2 title="{{ user }}" id="username-profile-page">{{ user|safe|linebreaksbr|truncatechars_html:25 }} {% if user.userprofileinfo.verified %} <span class="image-profile-verified"><img draggable="false" title="Verified User" class="verifed" src="{% static 'images\verified.png' %}" alt="verified" width="25" height="25" srcset=""></span> {% endif %}</h2>
<p>{{ user.first_name }} {{ user.last_name }}</p><br>
</div>
</div>
<div class="profile-page-user-desc-box">
<p>{{ user.userprofileinfo.description }}</p>
<p>{{ user.userprofileinfo.website }}</p>
<p>{{ user.userprofileinfo.joined_date |date:"F d Y" }}</p>
</div>
<br>
{% if user.userprofileinfo.image %}
<img class="rounded-circle account-img" src="{{ user.userprofileinfo.image.url }}" alt="{{ user }}'s Profile Picture'">
{% endif %}
</div>
<div class="user-post-user-profile-page">
<h1 title="{{ user }}">Posts</h1>
{% for post in posts %}
<div class="content">
<div class="post">
<h1 class='posttitle'>{{ post.title }}</h1>
<img class="user-image" src="{{ post.author.userprofileinfo.image.url }}" alt="pfp" width="20%" height="20%">
{% if post.published_date %}
<!-- <div class="postdate">
<i class="fas fa-calendar-day"></i> <p>Posted {{ post.published_date|timesince }} ago</p>
</div> -->
<div class="posted-by">
<p>Posted by <strong>{{ post.author }}</strong> {{ post.published_date|timesince }} ago</p>
</div>
{% else %}
<a class="pub-post" href="{% url 'mainapp:post_publish' pk=post.pk %}">Publish</a>
{% endif %}
<p class='postcontent' >{{ post.text|safe|linebreaksbr }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
And here is the user_posts page
{% block content %}
<div class="sidebar">
<p class="active" href="#">{{ view.kwargs.username }}</p>
<button class="commentbtn"><a class="aclass" href="#">Connect with {{ view.kwargs.username }}</a></button>
<p>{{ user.userprofileinfo.email }}</p>
<p>Lorem</p>
</div>
{% for post in posts %}
<div class="content">
<div class="post">
<h1 class='posttitle'>{{ post.title }}</h1>
<img class="user-image" src="{{ post.author.userprofileinfo.image.url }}" alt="pfp" width="20%" height="20%">
{% if post.published_date %}
<!-- <div class="postdate">
<i class="fas fa-calendar-day"></i> <p>Posted {{ post.published_date|timesince }} ago</p>
</div> -->
<div class="posted-by">
<p>Posted by <strong>{{ post.author }}</strong> {{ post.published_date|timesince }} ago</p>
</div>
{% else %}
<a class="pub-post" href="{% url 'mainapp:post_publish' pk=post.pk %}">Publish</a>
{% endif %}
<p class='postcontent' >{{ post.text|safe|linebreaksbr }}</p>
</div>
</div>
{% endfor %}
{% endblock %}
I have tried to merge the FBV into the CBV by cutting it and pasting it below the get_queryset method So like this
def get_queryset(self):
#... code here
def view_profile(request,pk=None):
#... code here
However this did not work. I am just curious as to how I can integrate both together so I can have the best of both worlds in one place
EDIT: Here are the models
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,max_length=30)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
description = models.CharField(max_length=150)
website = models.URLField(max_length=200)
image = ProcessedImageField(upload_to='profile_pics',
processors=[ResizeToFill(150, 150)],
default='default.jpg',
format='JPEG',
options={'quality': 60})
joined_date = models.DateTimeField(blank=True,null=True,default=timezone.now)
verified = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
and now the post
class Post(models.Model):
author = models.ForeignKey(User,related_name='posts',on_delete=models.CASCADE)
title = models.CharField(max_length=75)
text = models.TextField()
group = models.ForeignKey(Group,null=True,blank=True,related_name='posts',on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
image = models.ImageField(upload_to='post_images',blank=True,null=True)
file = models.FileField(upload_to='post_files',blank=True,null=True)
published_date = models.DateTimeField(blank=True,null=True,auto_now_add=True)
comments_disabled = models.BooleanField(default=False)
NSFW = models.BooleanField(default=False)
spoiler = models.BooleanField(default=False)
tags = TaggableManager()
def __str__(self):
return self.title
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
Also in continuation to Ian answer, if you have a direct relationship between models then you can simply get the posts for the particular user like this:
def view_profile(request,pk=None):
if pk:
user_profile = User.objects.get(pk=pk)
user_posts = Posts.objects.filter(user__id=pk) #<---add these
else:
user_profile = request.user
user_posts = Posts.objects.filter(user__id = request.user.id) #<---add these
context = {
'user':user_profile,
'user_posts':user_posts
}
return render(request,'mainapp/profile.html',context)
A simple class based view for getting a user:
class UserDetailView(DetailView):
model = User
template_name = 'mainapp/profile.html'
context_object_name = 'user'
Relationships (foreign keys) can be followed backwards. Every foreign key has a reverse relationship defined (unless you set reverse_name to +...) it will usually be named <modelname>_set on the model referenced by the foreign key
For example, the following two lines are equivalent
Post.objects.filter(author=user)
user.post_set.all()
This can be used in your profile template
{% for post in user.post_set.all %}
...
{% endfor %}
I've been going over the docs and some StackOverflow examples but I'm still having a little trouble. In Django I created a form, the view renders it and I have it displayed as form.as_p in the HTML template. This works perfectly, but I would like to be able to customize my HTML template instead of having it displayed as form.as_p. Any examples on how to do so?
So far I have the following.
View:
#login_required
def register(request):
info = Content.objects.get(id=request.user.id)
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, instance=info)
if form.is_valid():
info = form.save(commit=False)
info.save()
return HttpResponseRedirect('/portal/register')
else:
form = UploadFileForm(instance=info)
return render(request, 'portal/register.html', {'form': form, 'gallery': info})
Form:
class UploadFileForm(ModelForm):
logo = forms.ImageField(required=False)
image1 = forms.ImageField(required=False)
terms = forms.CharField(required=False)
class Meta:
model = Content
fields = ['user', 'logo', 'image1', 'terms']
Model:
class Content(models.Model):
user = models.ForeignKey(User)
logo = models.ImageField(upload_to=content_file_name, null=True, blank=True)
image1 = models.ImageField(upload_to=content_file_name, null=True, blank=True)
terms = models.CharField(max_length="256", blank=True)
def __unicode__(self):
return self.title
HTML Template:
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
{% if gallery.logo %}
<img class="img-responsive" id="logo" src="/media/{{ gallery.logo }}" alt="">
{% else %}
<img class="img-responsive" id="logo" src="/media/images/placeholder.png" alt="">
{% endif %}
</a>
<input type="file" name="logo" id="logo" multiple>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
{% if gallery.image1 %}
<img class="img-responsive" id="image1" src="/media/{{ gallery.image1 }}" alt="">
{% else %}
<img class="img-responsive" id="image1" src="/media/images/placeholder.png" alt="">
{% endif %}
</a>
<input type="file" name="image1" id="image1" multiple>
</div>
<div class="form-group">
<input type="text" name="terms" id="terms" class="form-control input-sm" placeholder="terms" value="{{ gallery.terms }}">
</div>
<input type="submit" value="Submit" />
</form>
Yes you can loop on the form fields by doing the following
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
<label>
{{ field.label_tag }}
</label>
<div>
{{ field }}
</div>
</div>
{% endfor %}
Then you can add class to the div and label tags and style the form fields
You can also use Django Widget Tweaks to add classed to the form fields.
Click here to read in more details
By using widget tweaks you simply find the field in which you want to add the class by doing this
{% load widget_tweaks %}
{{ form.name|add_class:"inputContact volunteer" }}
You can render the fields manually:
We don’t have to let Django unpack the form’s fields; we can do it
manually if we like (allowing us to reorder the fields, for example).
Each field is available as an attribute of the form using {{
form.name_of_field }}, and in a Django template, will be rendered
appropriately.
Example from the documentation:
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
As I said in the comments, see also Django Crispy Forms. You can achieve the same without so much markup.