I have built a photo gallery and I when an image is opened I would like to add to buttons ( Previous & Next) Which will cycle through my images based on their id/pk.
Models.py
class PostImage(models.Model):
image = models.ImageField(null=False, blank=False, upload_to="images", default="default.png")
image_title = models.CharField(max_length=100, null=False, blank=False, default="")
def __str__(self):
return self.image_title
class Meta:
verbose_name_plural = 'PostImage'
Views.py
def galleryPage(request):
images = PostImage.objects.all()
context = {'images':images}
return render(request, 'gallery.html', context)
def viewImage(request, pk):
photo = PostImage.objects.get(id=pk)
return render(request, 'viewimage.html', {'photo': photo})
HTML
<div class="image-container">
<div class="image-post">
<a href="{% url 'gallery' %}"
><img class="photo-img" src="{{photo.image.url}}"
/></a>
<h2 class="photo-title">{{photo.image_title}}</h2>
<p class="contact">
Interested in purchasing this as a print? Contact me for more
information regarding price and sizes.
</p>
<a href="{% url 'contact' %}" class="btn btn-secondary" type="button"
>Contact</a
>
</div>
</div>
</body>
</html>
Related
I am adding a simple review function on my Social platform Django project, where Users can write a review on another user's profile. But after posting the review, it's only showing on the profile page of the user that I'm currently signed in to.
This is my models.py
` class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
reviewmsg = models.TextField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.reviewmsg)`
views.py
` def userProfile(request, pk):
user = User.objects.get(id=pk)
rooms = user.room_set.all()
reviews = user.review_set.all()
if request.method == 'POST':
review = Review.objects.create(
user=request.user,
reviewmsg=request.POST.get('reviewmsg')
)
return redirect('user-profile', pk=user.id)
context = {'user':user, 'rooms':rooms, 'reviews':reviews}
return render(request, 'pages/profile.html', context)`
excerpt from my profile page template
` <div>
{% for review in reviews %}
<div class="comment-sect" style="margin-top: 0.5rem;">
<div class="comment-photo" style="margin: auto;">
<a href="{% url 'user-profile' review.user.id %}">
<div class="profile-photo">
<img src="{{review.user.avatar.url}}">
</div>
</a>
</div>
<div class="comment-info" style="width: 300px;">
<small>#{{review.user}}</small>
<small>{{review.created|timesince}} ago </small>
<p style="margin-bottom:0;">{{review.reviewmsg}}</p>
</div>
</div><!--end of comment-sect-->
{% endfor %}
<div class="comment-form" style="margin-top: 0.5rem; text-align:center;">
<form method="POST" action="">
{% csrf_token %}
<div>Submit a Review
<input type="text" name="reviewmsg" placeholder="What do you think about this User?"/>
</div>
</form>
</div>`
EDITED
As mentioned by #lain Shelvington, I agree that I need to add another ForeignKey to my models. I tried updating the models.py to:
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.ForeignKey(Profile, on_delete=models.SET_NULL, null=True)
reviewmsg = models.TextField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.reviewmsg)
and views.py to:
user = User.objects.get(id=pk)
rooms = user.room_set.all()
reviews = user.review_set.all()
if request.method == 'POST':
review = Review.objects.create(
user=request.user,
profile=user,
reviewmsg=request.POST.get('reviewmsg')
)
return redirect('user-profile', pk=user.id)
context = {'user':user, 'rooms':rooms, 'reviews':reviews}
return render(request, 'pages/profile.html', context)
but ended up with error:
ValueError at /profile/7/
Cannot assign "<User: celeste>": "Review.profile" must be a "Profile" instance
I want to redirected user to the profile page in the question model, I want when user click on url in the username of the question model, I want that url to redirected user to the author of that question to his/her public_profile page like facebook you can visit someone profile by clicking on his name when he/she post something, I have try using this method but it throws me an error: Reverse for 'Public_Profile' with arguments '('',)' not found. 1 pattern(s) tried: ['userProfile/(?P[-a-zA-Z0-9_]+)/\Z']
this is what i have try:
my urls:
urlpatterns = [
path('', views.rules, name='Rules'),
path('create', views.login, name='login'),
path('index/', views.index, name='index'),
path('view/<slug:slug>/', views.viewQuestion, name='view-Question'),
path('question/<int:pk>/answer/', views.My_Answer.as_view(), name='answer'),
path('question/', views.My_Question.as_view(), name='question'),
path('register/', views.register, name='register'),
path('feedback/', views.PostFeedBack.as_view(), name='FeedBack'),
path('notification/', views.NotificationListView.as_view(), name='notification'),
path('profile/<int:pk>/', views.profile, name='Profile'),
path('edit/<slug:slug>/', views.EditProfile.as_view(), name='edit'),
path('userProfile/<slug:slug>/', views.public_profile, name='Public_Profile'),
]
my index/home template:
<div class="container">
<div class="row justify-content-center">
{% for question in list_of_question reversed %}
<div class="col-md-4">
<div class="card my-3">
<div class="card-header">
<p class="card-title"><a href="{% url 'Public_Profile' profile.slug %}">
{{question.user.username.upper}}
</a></p>
</div>
<div class="card-body">
<a href="{% url 'view-Question' question.slug %}" style="text-decoration: none;">
<p class="card-title">{{question.title}}</p>
</a>
<h5>{{question.category}}</h5>
</div>
</div>
</div>
{%endfor%}
</div>
</div>
my views:
#login_required(login_url='login')
def index(request):
query = request.GET.get('q', None)
list_of_question = Question.objects.all()
if query is not None:
list_of_question = Question.objects.filter(
Q(title__icontains=query) |
Q(category__name__icontains=query)
)
unread_notifications =
Notification.objects.filter(user=request.user,
is_read=False).count()
paginator = Paginator(list_of_question, per_page=15)
context = [
{
'unread_notifications':unread_notifications,
'list_of_question':list_of_question,
'paginator':paginator
}
]
return render(request, 'index.html', context)
def profile(request, pk):
profiles = Profile.objects.filter(user=request.user)
questions = Question.objects.filter(user=request.user)
context = {
'profiles':profiles,
'questions':questions
}
return render(request, 'profile.html', context)
def public_profile(request, slug):
contents = get_object_or_404(Profile, slug=slug)
profiles = Profile.objects.filter(user=contents)
context = {
'contents':contents,
'profiles':profiles
}
return render(request, 'public_profile.html', context)
my model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.ImageField(upload_to='avatar', blank=True, null=True,
default='static/default.jpg')
stories = RichTextField(blank=True, null=True)
twitter = models.URLField(max_length=300, blank=True, null=True)
website = models.URLField(max_length=300,blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
location = models.CharField(max_length=80, blank=True, null=True)
slug = models.SlugField(unique=True, max_length=200)
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super(Profile, self).save(*args, **kwargs)
def __str__(self):
return str(self.user)
class Question(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, blank=False, null=False)
body = RichTextField(blank=False, null=False)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
slug = models.SlugField(unique=True, max_length=200)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Question, self).save(*args, **kwargs)
def __str__(self):
return str(self.title)
You should change profile.slug into question.user.profile.slug
Try this in your template:
<div class="container">
<div class="row justify-content-center">
{% for question in list_of_question reversed %}
<div class="col-md-4">
<div class="card my-3">
<div class="card-header">
<p class="card-title">
<a href="{% url'Public_Profile' question.user.profile.slug %}">
{{question.user.username.upper}}
</a></p>
</div>
<div class="card-body">
<a href="{% url 'view-Question' question.slug %}" style="text-decoration: none;">
<p class="card-title">{{question.title}}</p>
</a>
<h5>{{question.category}}</h5>
</div>
</div>
</div>
{%endfor%}
</div>
</div>
In template
<p class="card-title">
<a href="/profile/{{question.user}}">
{{question.user.username.upper}}
</a>
</p>
Views:
def profile(request, pk):
profiles = Profile.objects.get(user=pk)
questions = Question.objects.filter(user=pk)
context = {
'profiles':profiles,
'questions':questions
}
return render(request, 'profile.html', context)
The error is trying to tell you that django tried to call Public_Profile but it requires some slug. This is because profile is None in the template context. You need to change <a href="{% url 'Public_Profile' profile.slug %}"> with <a href="{% url 'Public_Profile' question.user.slug %}">
I'm trying to add search bar in my application but I don't know how to query a database to gives the things that user's search for. I want when user search for a user in a post or category in a post of model to shows the result that user search for, like YouTube search and facebook search, How can i do this in django to give me what i want ?
this is my model:
class Photo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.CharField(max_length=30,null=True, blank=False)
image = CloudinaryField(blank=False, null=False)
description = models.TextField(null=True)
date_added = models.DateTimeField(auto_now_add=True)
phone = models.CharField(max_length=12, null=False, blank=False)
price = models.CharField(max_length=30,blank=False)
location = models.CharField(max_length=20, blank=False)
def __str__(self):
return str(self.category)
my search form in dashboard template:
<div class="container">
<div class="row justify-content-center">
<form action="{% url 'search' %}" method="get">
<input class="form-control me-2" type="search" placeholder="Search" aria-
label="Search">
<br>
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
the post card in dashboard template:
<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>
the dashboard view:
def dashboard(request):
photos = Photo.objects.all()
context = {'photos': photos}
return render(request, 'dashboard.html', {'photos': photos} )
the search bar view:
def search(request):
return render(request, 'search.html')
urls:
path('', views.dashboard, name='dashboard'),
path('search/', views.search, name='search')
You can make it using filter method inside your view. Something like:
def dashboard(request):
photos_filter = request.GET.get('filtered[]', False)
photos = Photo.objects.all()
if photos_filter:
photos_filter = eval(photos_filter)
if photos_filter['id'] == 'category':
payments = payments.filter(
category__icontains=payments_filter['value'])
if photos_filter['id'] == 'user':
payments = payments.filter(
user__id=payments_filter['value'])
context = {'photos': photos}
return render(request, 'dashboard.html', {'photos': photos} )
And so on, you can add any filter you like. And in your URL you just add
/?filtered[]=%7B%22id%22:%22category%22,%22value%22:%22Nature%22%7D
Your code will see this filter like a dict obj: {'id': 'category', 'value': 'Nature'}. So after it, you'll get all photos with the category nature
I'm working a website where I want to display product that are of two categories which are premium and free package and I want to filter all the premium package and label it with a star or a premium text to indicate it a premium package and for the free I'll do nothing. I don't know if I should user foreign key for this or tuple.
models.py:
STATUS_CHOICE = (
('draft', 'Draft'),
('in_review', 'In Review'),
('published', 'Published')
)
class Package_Category(models.Model):
title = models.CharField(max_length=10000, verbose_name="Title")
slug = models.SlugField(max_length=1000, unique=True)
def get_absolute_url(self):
return reverse("package-categories", args=[self.slug])
def __str__(self):
return self.title
class Meta:
verbose_name = "Package Category"
verbose_name_plural = "Package Categories"
class Vectors(models.Model):
title = models.CharField(max_length=10000, null=True, blank=True, verbose_name="Title")
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to="vectors-images/%Y/%m/%d/", default="default.jpg", verbose_name="Image Cover")
vec_file = models.FileField(upload_to='vector-uploads/%Y/%m/%d/', null=True, blank=True, verbose_name="Upload File")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="Category")
package_category = models.ForeignKey(Package_Category, on_delete=models.CASCADE, verbose_name="Package Category")
tags = models.ForeignKey(Tag, on_delete=models.CASCADE, verbose_name="Tag")
status = models.CharField(choices=STATUS_CHOICE, default="published", max_length=150, verbose_name='Status')
creator = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Creator")
creator_image = models.ImageField(upload_to="creators-images/%Y/%m/%d/", default="default.jpg", verbose_name="Creator Image")
created = models.DateTimeField(verbose_name="Created")
class Meta:
verbose_name = "Vector"
verbose_name_plural = "Vectors"
def get_absolute_url(self):
return reverse("vector-details", args=[self.slug])
def __str__(self):
return self.title
index.html:
{% for vector in vectors %}
<!-- Single Pricing Box -->
<div class="col-lg-4 col-md-6 col-sm-12">
<div class="_45lio">
<div class="_jk58o item_image_urip">
<img src="{{vector.image.url}}" class="img-fluid" alt="">
<i class="fa fa-download"></i>
<div class="image_urip_caption">
<div class="urip_caption_flex">
<div class="urip_author">
<div class="urip_avater">
<a href="author-detail.html.html" class="author-img">
<img src="assets/img/author.png" class="img-fluid" alt="" />
</a>
</div>
<div class="urip_avater_place">
<h3 class="urip_title">Adam vilson</h3>
<span>Liverpool, London</span>
</div>
</div>
</div>
<div class="urip_caption_last">
<div class="item_list_links">
<i class="fa fa-plus-circle"></i>
<i class="fa fa-heart"></i>
</div>
</div>
</div>
<div class="_io980 item_image_urip">
{% if package_category.premium %}
<h1>Premium Package</h1>
{% else %}
<h1>Free Package</h1>
{% endif %}
<h4 class="_95lp">{{vector.package_category}}</h4>
<span class="_ip76n">{{vector.category}}</span>
</div>
</div>
</div>
</div>
{% endfor %}
views.py:
from django.shortcuts import render
from . models import Vectors, Tag, Category, Package_Category
def index(request):
vectors = Vectors.objects.filter(status='published').order_by('-created')
context = {
'vectors': vectors,
}
return render(request, 'index.html', context)
you should do something like this if you are not using drf just by using the same model.
def index(request):
vectors = Vectors.objects.filter(status='published', package_category__title =="premimum").order_by('-created')
if vectors.exists():
// do something:
context = {
'vectors': vectors,
}
return render(request, 'index.html', context)
Although the best option would be to use serializers with drf
I am having a challenge displaying multiple images users post to one img template element, for one reason if i try fetching images with the default related name it wouldn't show in the template and i wonder what i am doing wrong. Can anyone be of help!
Here is my model for post.
class Post(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, related_name="page")
username = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE ,related_name="page_user")
description = models.TextField(max_length=500, blank=True)
video = models.FileField(upload_to="PageVideos", blank=True)
pic = models.ImageField(blank=True)
date_posted = models.DateTimeField(auto_now_add=True)
tags = models.CharField(max_length=100, blank=True)
class Mete:
ordering = ['-date_posted']
def __str__(self):
return self.description
class PostImage(models.Model):
#page = models.ForeignKey(Page, on_delete=models.CASCADE, related_name="pg")
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
images= models.ImageField(upload_to="postimages/")
Here is my Detail view
def page_detail(request,id):
post = get_object_or_404(Post, id=id)
photos = PostImage.objects.filter(post=post)
context = {
'post':post,
'photos':photos
}
return render(request, 'page/detail.html',context)
These my Template to display users images
<div class="p-3 border-b dark:border-gray-700">
{{ post.description }}
</div>
<div uk-lightbox>
<div class="grid grid-cols-2 gap-2 p-2">
{% for p in photos.images_set.all %}
<a id="images" href="{{ p.images.url }}" class="col-span-2" >
<img src="{{ p.images.url }}" alt="" class="rounded-md w-full lg:h-76 object-cover">
</a>
<a href="">
<img src="" alt="" class="rounded-md w-full h-full">
</a>
<a href="" class="relative">
<img src="" alt="" class="rounded-md w-full h-full">
<div class="absolute bg-gray-900 bg-opacity-30 flex justify-center items-center text-white rounded-md inset-0 text-2xl"> + see more </div>
</a>
{% endfor %}
</div>
</div>
your photos is a list you dont need reverse m2m (the "images_set") simply change this in html
....
<div class="grid grid-cols-2 gap-2 p-2">
{% for p in photos %}
....
for optimize you can do this
from django.http import Http404
...
def page_detail(request,id):
try:
# with prefetch you do only one sql request
post = Post.objects.select_related('images_set').get(id=id)
expect Post.DoesNotExist as err:
raise Http404(err)
context = {
'post': post,
'photos': post.images_set.all()
}
return render(request, 'page/detail.html',context)