Link an user to his profile page - django

How do I link the logged in user to his profile page?
{% if user.is_authenticated %}
Profile
Here are the involved parts:
views.py
#login_required
def profile(request, profile_id):
if profile_id == "0":
if request.user.is_authenticated:
userProfile = UserProfile.objects.get(pk=profile_id)
else:
userProfile = UserProfile.objects.get(pk=profile_id)
return render_to_response('blog/profile.html', {'userProfile':userProfile}, RequestContext(request))
urls.py
url(r'^profile/(?P<profile_id>\d+)/$', views.profile),
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.TextField(max_length=500, blank = True, default=('keine Angabe'), null=True)
image = models.FileField(null=True, blank=True)
def __unicode__(self):
return self.user.username

In you template you are trying to use url tag with named urls even though you haven't passed name keyword argument to url function in your urlpatterns.
In your urls function pass name argument, like this:
url(r'^profile/(?P<profile_id>\d+)/$', views.profile, name='profile'),
make sure you namespaced the app as 'blog' in your root url conf.
In your template to access current user's profile id by request context's user object. Like this:
{% if user.is_authenticated %}
Profile

Related

how can show profile User in html django

i create user auth and make model profile user with signals to create profile like User
but i want show user profile in template
---- model
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
# Create your models here.
class profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
music = models.CharField(max_length=50)
skils = models.CharField(max_length=50)
search = models.CharField(max_length=50)
posts = models.CharField(max_length=50)
boi = models.TextField()
img = models.ImageField(upload_to="profile-img")
def __str__(self):
#return self.user or 'User'
return str(self.id)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = profile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
---- path
path('profile/<int:id>', views.profile, name="profile")
----- views
def profile(request, id):
ff = profile.objects.get(id=id)
context = {'ff' : ff}
return render(request, 'profile.html', context)
views not work i dont know the problem
in html...
{% url 'profile' profile.id %}
how can show profile User in html django
If you want User can show his Profile, you need to get the Profile object using the current user instance instead of profile id like this...
views.py
def profile(request):
ff = profile.objects.get(user=request.user) # This query object give logged in user profile
context = {'ff' : ff}
return render(request, 'profile.html', context)
Profile url path become like this
urls.py
path('profile/', views.profile, name="profile")
Html url becomes like this
{% url 'profile' %}
NOTE - No need pass id of profile because here we get profile of current user which is logged in

Django: Unable to access attribute of foreign key

I have a Comment model with User as a foreign key, and simply want to render the username of the comment. The comment shows up on the page but the username doesn't, I've tried comment.user and comment.user.username and neither works and I'm not sure why.. Sorry if this is a really basic question.
class Comment(models.Model):
comment = models.TextField(default="")
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, default=1)
def comment(request, listing_id):
listin = Listing.objects.get(id=listing_id)
if request.method == "POST":
comment = CommentForm(request.POST)
if comment.is_valid():
comment = comment.save(commit=False)
comment.user = request.user
comment.listing = listin
comment.save()
return redirect("listing", listing_id=listing_id)
HTML code:
{% for comment in comments %}
<p>{{ comment.user.username }}: {{ comment.comment }}</p>
{% endfor %}
Edit:
I have sinced removed the blank=True and null=True arguments for user in the Comment model so it looks like this, migrated the changes and added a few comments, the username still doesn't render even though the username shows up as a field value in the admin view for the Comment object.
class Comment(models.Model):
comment = models.TextField(default="")
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, default=1)
My User class simply inherits from the AbstractUser model
class User(AbstractUser):
watchlist = models.ManyToManyField(Listing)
def __str__(self):
return self.username
Assuming that User is the admin user, if you are not already logged as admin then the comment will be saved without a user as request.user is None.
You can force the user to be logged in by adding the login_required decorator before the view function
from django.contrib.auth.decorators import login_required
...
#login_required
def view(request)
...
This way you can only comment if you are already logged in and if not, then you will be redirected to the login page and once you are logged in the comment will be saved.
I see there you have no user data, you have to do this to prevent user comments from being available
from django.contrib.messages import error
from django.urls import reverse
from django.contrib.auth.decorators import login_required
#login_required
def comment(request):
if not request.user.is_authenticated:
error("....")
return redirect(reverse("foo"))
...

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.

Django ImageField won't upload in function based view, but it does in the admin

I've been trying to add some user uploaded profile picture to my website. It works fine when I do it from the admin, the image is showed and all the engines seems to be working fine (image going to the correct upload location and so on). The problem is when I try to do the same thing from my view.
I noticed that the print("upload_location") only appears when I do it from the admin. The weird thing is that all the other fields in my Profile model are working fine (like name "foo" is updated to "foobar") and not only in the admin, but in the view as well. The issue is only with the ImageField.
I believe it could have something to do with the way I'm handling the form.is_valid(), but I've been playing around with that and nothing changed (I know it is working to some extend, since HttpResponseRedirect is working.
Any ideas?
views.py
...
#login_required
def profile_update(request, username=None):
obj = get_object_or_404(User, username=username)
user = obj.profile
form = ProfileForm(request.POST or None, instance = user)
context = {
"form": form
}
if form.is_valid():
form.save()
return HttpResponseRedirect('/profiles/{username}'.format(username=user.user))
template = 'profile_update.html'
return render(request, template, context)
forms.py
from django import forms
from .models import Profile
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
"profilePic",
"nome",
...
]
def profile(self, request, user):
print('printing forms')
user.uf = self.cleaned_data['uf']
user.cidade = self.cleaned_data['cidade']
user.telefone = self.cleaned_data['telefone']
user.save()
models.py
...
User = settings.AUTH_USER_MODEL # 'auth.User'
def upload_location(instance, filename):
print("upload_location")
return "%s/%s" %(instance.user, filename)
class Profile(models.Model):
user = models.OneToOneField(User)
id = models.AutoField(primary_key=True)
width = models.IntegerField(default=0, null=True, blank=True,)
height = models.IntegerField(default=0, null=True, blank=True,)
profilePic = models.ImageField(
upload_to = upload_location,
blank=True, null=True,
verbose_name = 'Foto de Perfil',
width_field="width",
height_field="height",
)
...
template.html
...
<form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Enviar" class="btn btn-primary"/>
</form>
...
You need to add FILES into the form.
form = ProfileForm(request.POST or None, request.FILES or None, instance = user)
Docs: https://docs.djangoproject.com/en/1.10/topics/http/file-uploads/

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