pick id of the user who is not logged in - django

In this my views I get users by their exact name example www.mysite.com/usuario1
and so far it's working, but I need it in the photos section to get only the photos of that user1
and that user1 is not logged into the system.
how do I pull only the photos of the user1?
models.py
class Photo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255, blank=True)
file = StdImageField( upload_to='photos/', blank=False, variations={
'large': (600, 400),
'thumbnail': (100, 100, True),
'medium': (300, 200),
})
uploaded_at = models.DateTimeField(auto_now_add=True)
class Negocio(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
views.py
def profile_detail(request, username):
if User.objects.get(username__iexact=username):
user_details = User.objects.get(username__iexact=username)
photos_list = Photo.objects.filter(user=request.username.pk)
return render(request, "profile.html", {
"user_details": user_details, 'photos': photos_list
})
else:
return render("User not found")
profile.html
{% for photo in photos %}
<img src="{{ photo.file.medium.url}}"class="img-thumbnail" width="200" height="200">
{% endfor %}

Well, you get the user, but then you don't pass it to your Photo filter - instead you pass the logged-in user there. Just use the user you got:
photos_list = Photo.objects.filter(user=user_details)
Note, your first line will fail if the user does not exist, because the query will raise a DoesNotExist exception. A better way to do it would be:
def profile_detail(request, username):
user_details = get_object_or_40o4(User, username__iexact=username)
photos_list = Photo.objects.filter(user=user_details)
return render(request, "profile.html", {
"user_details": user_details, 'photos': photos_list
})
which will automatically show a 404 (not found) page if the username does not exist.

You don't need a queryset for the photos, you can access them through the User instance using the related_name, if you don't set a related_name you can just append _set to the model name like this:
photos_list = user_details.photo_set.all()
But you don't really need the queryset at all in your view, in your template you can do this:
{% for photo in user_details.photo_set.all %}
<img src="{{ photo.file.medium.url}}"class="img-thumbnail" width="200" height="200">
{% endfor %}

Related

Unable to load logged in User's Profile Image in Django template

This is my frontend code of header.html where I am typing to display the currently logged-in user's profile picture after the user authenticates. It works when my current user is on the home page or its profile but as soon as it moves to another's profile it starts displaying that profile's picture. I want to make it such like where ever logged in user move he/she should always see their profile picture
<div><b>Bondly</b></div>
{% if user.is_authenticated %}
<div>
-------> <img src="{{user_profile.img_profile.url}}" />
</div>
{% endif %}
</header>
Here are code of my views.py
def profile(request, pf):
user_object = User.objects.get(username=pf)
user_profile = models.Profile.objects.get(usr=user_object)
print(request.user.__doc__)
posts = models.Post.objects.filter(user=pf)
postsNum = len(posts)
follor = request.user.username
if models.Followers.objects.filter(follower=follor, user=pf).first():
text = "Following"
else:
text = "Follow"
followers = len(models.Followers.objects.filter(user=pf))
following = len(models.Followers.objects.filter(follower=pf))
context = {
'user_object': user_object,
"user_profile": user_profile,
"posts": posts,
'postsNum': postsNum,
"text": text,
"followers": followers,
"following": following
}
return render(request, 'profile.html', context)
and my models.py
class Profile(models.Model):
"""docstring for Profile."""
usr: str = models.ForeignKey(User, on_delete=models.CASCADE)
id_usr: int = models.IntegerField()
Fname:str = models.TextField(blank=True,null=True)
Mname:str = models.TextField(blank=True,null=True)
Lname:str = models.TextField(blank=True,null=True)
Fhone:int = models.IntegerField(blank=True,null=True)
bio: str = models.TextField(blank=True)
img_profile = models.ImageField(
upload_to='ProfileIMG', default="blankprofile.png")
location: str = models.CharField(max_length=250)
def __str__(self):
return self.usr.username
You can simply use request.user to get logged in users data from your models in any template. The way you are currently loading user image is different, as it will load data of the user only when user data is passed in context for the template
{% if request.user.is_authenticated %}
<div>
<img src="{{ request.user.profile.img_profile.url }}" />
</div>
{% endif %}

How I can get the pk in the home view www.mywebsite.com

I tried to get the pk from this function def home_view(request, pk): but because this in home view www.site.com it return error home_view() missing 1 required positional argument: 'pk' so it is didn't worked with me
My qustion is how I can pass pk to the template that in website domain without any extra urls like this
www.site.com
My view
def home_screen_view(request, pk, *args, **kwargs):
post= Post.objects.filter(pk=pk) #here I want to get the pk
comment = PostCommentIDF.objects.filter(post=post)
return render(request, 'personal/home.html', {'comment': comment)
My Urls
path('', home_screen_view, name='home'),
Edit
Firstly I return my posts using list [], I need the pk of the post because the comment model is separate from the post model so I use the pk to use in this function
posts = Post.objects.filter(pk=pk)
comment = PostCommentIDF.objects.filter(post=post)
post = []
for u in users:
p = Account.objects.get(username=u)
posts = p.post_set.all()
p_posts = p.video_set.all()
post .append(p_posts)
my_posts = request.user.post_set.all()
post.append(my_posts)
if len(post):
post = sorted(chain(*post), reverse=True, key=lambda post: post.created_date)
My comment MPTT model
class PostCommentIDF(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='pos_com')
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='post_children')
author = models.ForeignKey(Account, on_delete=models.CASCADE)
content = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
My Post Model
class Post(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
article = models.TextField(null=True, blank=True)
photo_article = models.ImageField(max_length=255, upload_to=get_poster_filepath)
created_date = models.DateTimeField(auto_now_add=True)
My template that related to render the comments
{% recursetree video.total_comts %}
<div id="{{ node.id }}" class="my-2 p-2" style="border: 0px solid grey">
<div class="d-flex justify-content-between">
{{ node.publish|naturaltime }}
<div class="node-content mt-3">{{ node.content }}</div>
</div>
{% endrecursetree %}
Solution One
As you do not pass the pk information from url, you can't use pk in the view. So change the view to:
def home_screen_view(request):
#rest of the code
Instead of pk, if you want to see the logged in user's posts, you can use:
def home_screen_view(request):
posts = Post.objects.filter(account__user=request.user) # assuming there is a FK relation in Account model.
Solution Two
Also, you can't find pk arbitarily in the home view at / url, unless you pass it like /12/, if you pass that value then you need to update url code:
path('<int:pk>/', home_screen_view, name='home'),
Solution Three
You can use url querystring to get the primary key:
def home_screen_view(request):
pk = request.GET.get('pk', None)
posts = Posts.objects.all()
if pk:
posts = posts.filter(pk=pk)
Then use the browser url should look like https://example.com/?pk=1.
Update
If you want to get post specific comments, then you can use following solution:
# view
def home_screen_view(request):
return render(request, 'personal/home.html', {'posts': Post.objects.filter(author__user=request.user)})
# template
{% for post in posts %}
{% for comment in post.comment_set.all %} // if you use related_name in PostCommentIDF then you need to use post.<related_name>.all
{{ comment }}
{% endfor %}
{% endfor %}

How to query a user's display information in the AccountDisplayInformation from the AccountModel

Account is my AUTH_USER_MODEL and AccountDisplayInfo consists of all the additional display info of every account. So they can input and submit, and subsequently update their information. These are my codes, but I'm unsure why it isn't working. First of all, I am receiving this error:
DoesNotExist at /account/5/displayinfo/ AccountDisplayInfo matching query does not exist.
Secondly, the "update" function isn't working.
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
class AccountDisplayInfo(models.Model):
account = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
instagram = models.CharField(max_length=50, unique=True, blank=True, null=True) #instagram
.html
<form method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-primary btn-sm col-lg-5">Update</button>
</div>
</form>
views.py
def display_information_view(request, *args, **kwargs):
user_id = kwargs.get("user_id")
account = Account.objects.get(pk=user_id)
context = {}
displayinfo = AccountDisplayInfo.objects.get(account=account)
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
info.save()
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
return redirect("account:view", user_id=account.pk)
else:
form = DisplayInformationForm(request.POST, instance=request.user,
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
else:
form = DisplayInformationForm(
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
return render(request, "account/displayinfo.html", context)
forms.py
class DisplayInformationForm(forms.ModelForm):
class Meta:
model = AccountDisplayInfo
fields = ('instagram')
Also, would be great if you can advise on this::
If I have 2 tables. Table 1 and Table 2. Table 2 has a foreign key to table 1 but table 1 dont have a foreign key to table 2. How can I query table 2's data from table 1? Thanks
By default .get() will return a DoesNotExist exception if no object matches the query you executed and stop the code from running, so if you want to input it manually on the same page use filter instead:
displayinfo = AccountDisplayInfo.objects.filter(account=account).first()
Then in your template do something like this:
{% if displayinfo %}
... show display info...
{% else %}
<p> No info yet </p> <!-- (or show some form) -->
{% endif %}
To answer your other question:
You have to use the related_name or related models attribute to access the ForeignKey data or use the model name with the _set suffix, for example:
class Post(models.Model):
title = models.CharField(max_lenght=10)
class Comment(models.Model):
body = models.CharField(max_lenght=200)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
then you would get the Post and its comments:
post = Post.objects.get(pk=1)
comments = post.comments.all()
if you didn't have the related_name attribute in your model field you would do this instead:
comments = post.comment_set.all()
UPDATE
Maybe the issue is in your Form class, try removing the save method from it and instead do this in your view:
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
info.save()
return redirect("account:view", user_id=account.pk)

how can i display other user information in django

I'm creating a website that the user can look at other users profile but the problem is when the user enter another user profile it show his personal information
this is the urls.py file code
urlpatterns = [
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
]
this is the view.py file code
class UserPostListView(ListView):
model = Post = Profile
template_name = 'website/user_posts.html'
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user)
def get_username_field(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Profile.objects.filter(user=user)
this is the models.py file
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
age = models.IntegerField(verbose_name='Ålder', default=15,
blank=True)
def get_absolute_url(self):
return reverse('user_posts', kwargs={'pk': self.pk})
def __str__(self):
return f'{self.user.username} Profile'
user_posts.html file
{{ user.get_full_name }}
{{ user.profile.age }}
{{ view.kwargs.username }}
in the template it's show the username but it didnt' show the name and the age.
user is always the current logged-in user. Your view uses the Profile model, so you can either access profile or object.
{{ profile.user.get_full_name }}
{{ profile.age }}
Note, your get_username_field method is never called and does not do anything; you should remove it.
Note also, it's really not a good idea to store age as an integer in the database. That means you somehow have to update it every year, as people have a strange habit of getting older... Better to store the date of birth, and have a method to display the age.
First of all your get_username_field is of no use.
In your views.py,
class UserPostListView(ListView):
model = Profile
template_name = 'website/user_posts.html'
context_object_name = 'user_content'
allow_empty = False #this will show 404 if the username does not exists
def get_queryset(self):
return User.objects.filter(username=self.kwargs['username'])
# you can do it in one line now
Now to show this in html,
{% for user in user_content %}
{{user.get_full_name}}
# rest of your code
{% endfor %}
You can also show posts of that particular user in same way as above.

How to route DetailView to inherit user and slug

I have a fairly simple DetailView:
class TrackDetails(DetailView):
model = Track
And in my urls.py:
url(r'^(?P<slug>[-\w]+)/$', TrackDetails.as_view(), name='track-details'),
The model:
class Track(models.Model):
....
# Variables
track_type_choices = [
('ORG', 'Original'),
('RMX', 'Remix'),
('CLB', 'Collab'),
('LIV', 'Live'),
]
# Model Fields
user = models.ForeignKey(User, unique=False)
title = models.CharField(max_length=100)
desc = models.TextField(max_length=7500)
track_type = models.CharField(max_length=3,
choices=track_type_choices,
default='ORG')
track_type_content = models.CharField(max_length=100,blank=True)
created = models.TimeField(auto_now=True,auto_now_add=False)
upload = models.FileField(upload_to=generate_user_folder_tracks,storage=OverwriteStorage(),validators=[is_mp3])
albumart = models.ImageField(upload_to=generate_user_folder_art,storage=OverwriteStorage(),validators=[is_square_png])
private = models.BooleanField(default=False)
downloadable = models.BooleanField(default=False)
likes = models.ManyToManyField(User, related_name="likes",blank=True)
dislikes = models.ManyToManyField(User, related_name="dislikes",blank=True)
plays = models.BigIntegerField(default=0)
slug = models.SlugField(max_length=50,unique=True)
The model displayed in the view has a "user" field connected to the user model, I want to use this in the url, so that instead of writing "www.domain.com/slug/" I would write "www.domain.com/user/slug" to access the view of the instance.
Additionally, I have extended the User model with a field called "Display_name", I'd like to show this field instead of the username in my template (track_detail.html):
{% include '__header.html' %}
{% load static from staticfiles %}
<div id="track_container">
<div id="track_titleinfo">
<div id="track_artist" class="text">{{ object.user }}</div>
<div id="track_title" class="text">{{ object.title }}</div>
{% if object.track_type == 'ORG' %}
{% else %}
<div id="track_type" class="text">({{object.track_type_content}})</div>
{% endif %}
</div>
</div>
{% include '__footer.html' %}
<img src="/static/users/{{ object.user }}/art/{{ object.slug }}.png" alt="">
The div with the ID "track_artist" displays the raw username (In this case, enitoni), I'd like it to display the display_name (In this case "Ekchö") from the userprofile class of the user who owns the Track instance:
class UserProfile(models.Model):
user = models.OneToOneField(User)
display_name = models.CharField(max_length=50, default="null")
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
To include the username in the detail view, you first need to add it to your url patterns.
url(r'^(?P<username>[-\w]+)/(?P<slug>[-\w]+)/$', TrackDetails.as_view(), name='track-details'),
Then, since you are using DetailView, you need to override get_object so that you use the username and slug to fetch the object.
from django.shortcuts imporg get_object_or_404
class TrackDetails(DetailView):
model = Track
def get_object(self, queryset=None):
return get_object_or_404(
Track,
user__username=self.kwargs['username'],
slug=self.kwargs['slug'],,
)
Displaying the display_name of the user in the template is a separate problem. If you have a user, you can follow the one to one key backwards to the profile with user.userprofile. Therefore, in your template you can show the display_name with.
{{ object.user.userprofile.display_name }}
To access username and slug first pass in the two keywords:
url(r'^/(?P<username>\d+)/(?P<slug>[-\w]+)/$', get_userpage, name='track-details'),
Then check if Track.objects.filter(slug=slug, username=username) returns anything:
def get_userpage(request, username, slug):
"""Render user page"""
user = User.objects.get(username=username)
track_song = Track.objects.filter(slug=trackslug, user=user).first()
if track_song:
# return song page for user
else:
# try to return user
track_user = Track.objects.filter(user=user).first()
if track_user:
# return user page
# if nothing returned above
# return 404
Previous suggestions:
you can you use get_object_or_404(Track, slug=slug) in your view to return the correct response.
you could also redirect a user to their unique combination of username and slug using:
redirect('track-username-slug', username=myusername slug=myslug, permanent=True)
where track-username-slug is your named url