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.
Related
I got the images working on my template, but the image being displayed is the current logged in user's image.
How do I filter it so that Profile.objects.get(user=[the owner of the post's user])?
class PostListView(ListView):
model = Post
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
context['user_post'] = Post.objects.filter(user_id=self.request.user.id)
# context['user_profile'] = Profile.objects.get(user=self.request.user.id)
context['user_profile'] = Profile.objects.get(user=1)
return context
The error code says: 'PostListView' object has no attribute 'user'. I don't understand this error code because from my understand PostListView's model is set to Post which has the following models:
class Post(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
...
So in other words every post made to the blog has a user.
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
context['user_post'] = Post.objects.filter(user_id=self.request.user.id)
# context['user_profile'] = Profile.objects.get(user=self.request.user.id)
context['user_profile'] = Profile.objects.get(user=1)
return context
What I believe self is doing here is represents the current object in PostListView right?
Can you please ELI5? I am having some trouble understanding the documentation since the language used in there is difficult for me.
Try something like this,
class PostListView(ListView):
template_name = 'add_template_name.html'
model = Post
context_object_name = 'all_posts'
def get_queryset(self):
return Post.objects.all()
Now in your template add this,
{% for post in all_posts %}
<img src="{{ post.user.profile_picture }}" alt="image">
<p> {{ post.title }} </p>
{% endfor %}
Whenever you want to use foreign key element, in this case user, you can choose post.user. Assuming your user model has profile_picture and username, you can display them as post.user.profile_picture and post.user.username respectively. For more info, you can go through Django docs.
Intro: I have a 3 models user, post, group. User is able to make posts however each post has to belong to a group. Users have to choose from the existing groups for their posts. Users cannot add, delete, update group's.
Furthermore:
Users can become a member of groups and when they click on a certain group. They see all the posts in that group.
What I want When Users come on the home page they see posts that were added since the last time they logged in
My Models
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts')
group = models.ForeignKey(Group, related_name='posts')
title = models.CharField(max_length=250, unique=True)
message = models.TextField()
created_at = models.DateTimeField(auto_now=True)
My Views
class Homepage(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super(Homepage, self).get_context_data(**kwargs)
if self.request.user.is_authenticated():
context['object_list'] = Group.objects.filter(members=self.request.user)
#The last login actually shows the users current login time as the last login. Which makes the below line of code useless
new_posts = Post.objects.filter(created_at__gt=self.request.user.last_login).count()
context['new_posts'] = new_posts
else:
context['object_list'] = Group.objects.all()
return context
In my templates I have
<div class="list-group">
{% for group in object_list %}
{% if not new_posts %}
{{group.post.count}}
{% else %}
{{new_posts}}
{% endif %}
{% endfor %}
</div>
The Issue: The last login actually shows the users current login time as the last login. Is there a way to get users last logout time instead of last login time example user.last_logout
I have the below answer but it doesn't seem to work for me
Django created_at__gt=self.request.user.last_login workinly only on users already signed in.
My profile create function
def signup(request):
if request.method == 'POST':
form = UserCreateForm(request.POST or None)
if form.is_valid():
new_user = form.save()
Profile.objects.create(user=new_user)
return redirect('accounts:edit_profile')
here is an example
class ProfileModel(models.Model):
#fields
last_time_logout = models.DateTimeField()
In a custom view, record the last logout
import datetime
def signout(request):
profile = reques.user.profile # it depends
if request.is_ajax(): # Do it with ajax
logout(request)
profile.last_time_logout = datetime.datetime.now()
profile.save()
return redirect("signin")
raise PermissionDenied
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
I've got these two models.
class UserProfile(models.Model):
user = models.OneToOneField(User)
THIS SHOULD BE
def posts(self):
return self.user.poster.all()
INSTEAD OF
def posts(self):
return self.user.post_set.all()
def __unicode__(self):
return self.user.username
class Post(models.Model):
author = models.ForeignKey(User, related_name='poster')
def __unicode__(self):
return self.title
and I'm attempting to display all posts by a user on this html page, where user_list = UserProfile.objects.all()
{% for user in user_list %}
{{ user.user }}
{{ user.posts }}
{% endfor %}
However, I'm being greeted by this error page that says 'UserProfile' object has no attribute 'post_set', or 'UserProfile' object has no attribute 'post_set', depending on if I use user.user.posts or user.posts.
Anyone have any ideas?
Thanks
In your Post class you have defined the related name of your ForeignKey to User as poster. This means you can access all of a user's posts through user.poster.all().
So your the posts method of your UserProfile class should be as follows:
def posts(self):
return self.user.poster.all()
In you example User does not have post_set attribute. If you want to get all posts for related User try this:
self.user.post.all()
I'm trying to add a new feature to my existing app that let users create a profile and upload a pictures of their pets.
When a user login , he gets redirected into the profile which display his name and also he can add a picture of himself into the model which will get displayed on the profile page.
At the moment , I can retrieve the name into the template but I can't seem to display the user's name and upload picture at the same time.
Whenever I click Add picture , It doesn't let the user upload a picture instead I get this error
'PictureForm' object has no attribute 'save'
pet = form.save(commit =False) ...
I could design the page to let the user upload a picture but not display the name at the same time.
I think the problem lays in my profile.html and Profile function at views.py
Parts of my views.py
#login_required
def Profile(request):
Person = request.user.get_profile()
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if request.method == "POST":
form = PictureForm(request.POST ,request.FILE or None)
if form.is_valid():
pet = form.save(commit =False)
pet.save()
context = (
{'Person': Person} ,
{'form':PictureForm()}
)
return render_to_response('profile.html', context, context_instance=RequestContext(request))
Parts of my forms.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from pet.models import *
class PictureForm(forms.Form):
class Meta:
model = Person
fields = ('image')
My profile.html
{% if Person %}
<ul>
<li>Name : {{Person.name}} </li>
</ul>
{% endif %}
<form method="POST" enctype="multipart/form-data" "action" >
{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type = "submit" value= "Add Picture" />
</form>
My models.py
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class Person(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
def __unicode__(self):
return self.name
class Pet(models.Model):
Person = models.ForeignKey(Person)
description = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
def __unicode__(self):
return self.description
PictureForm needs to inherit from forms.ModelForm, not forms.Form.
Erase your form.save(commit=False). You will only do that if you override your save method
#login_required
def Profile(request):
Person = request.user.get_profile()
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if request.method == "POST":
form = PictureForm(request.POST ,request.FILES)
if form.is_valid():
form.save()
context = (
{'Person': Person} ,
{'form':PictureForm()}
)
return render_to_response('profile.html', context, context_instance=RequestContext(request))
UPDATE:
[.....]
board = Board.objects.get(board=picture.board)//remove this
the_id = board.id //remove this
return HttpResponseRedirect(reverse('world:Boat', kwargs={'animal_id': picture.board.id })) // change the_id into picture.board.id
You have a typo. It should be request.FILES.
no buddy. your problem is in your model.py:
just add this function to your model
def save(self,*args, **kw):
super(PictureForm,self).save(*args, **kw)