I'm trying to create user Profile for my django project, I'm using UpdateView
to allow user to edit Profile model when they want to create profile for their account but it return an error every time I click on create profile url in the profile template.
Profile Template:
<div >
<div >
{% for profile in profiles %}
<div >
<a href="{{profile.website}}">{{profile.website}}</a>
<a href="{{profile.twitter}}">{{profile.website}}</a>
</div>
{% endfor %}
</div>
</div>
<br>
<div >
<div >
<a href="{% url 'editProfile' user.id %}" >Create Profile</a>
</div>
</div>
My model:
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
profile_image = models.ImageField(upload_to="avatars/")
stories = models.TextField(max_length=500,blank=True, null=True)
website = models.URLField(max_length=250, blank=True, null=True)
twitter = models.URLField(max_length=250, blank=True, null=True)
location = models.CharField(max_length=50, blank=True, null=True)
slug = models.SlugField(blank=True, null=True)
my urls:
path('editprofile/<slug:slug>/edit', views.EditProfileView.as_view(), name='editProfile'),
my views:
@login_required(login_url='login')
def profile(request, pk):
profiles = Profile.objects.filter(user=request.user)
questions = Question.objects.filter(user=request.user)
context = {'questions':questions, 'profiles':profiles}
return render(request, 'profile.html', context)
class EditProfileView(UpdateView):
model = Profile
fields = ['profile_image', 'stories', 'website', 'twitter', 'location']
template_name = 'edit_profile.html'
success_url = reverse_lazy('index')
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super(Creator, self).save(*args, **kwargs)
CodePudding user response:
Firstly fix
def save(self, *args, **kwargs):
self.slug = slugify(self.user.field) #field is what you want to slugfiy
super(Creator, self).save(*args, **kwargs)
secondly
You are sending ID but url requires slug
#old
<a href="{% url 'editProfile' user.id %}" >Create Profile</a>
#should be
<a href="{% url 'editProfile' user.slug_field %}" >Create Profile</a>
CodePudding user response:
You have made user
a OneToOneField
in your Profile
model, that means you should not use filter()
in profile
view, you should use get_object_or_404
for getting single user's profile, as it has OneToOneRelation
.
Try this:
from django.shortcuts import get_object_or_404
@login_required(login_url='login')
def profile(request, pk):
profile = get_object_or_404(Profile,user=request.user)
questions = Question.objects.filter(user=request.user)
context = {'questions':questions, 'profile':profile}
return render(request, 'profile.html', context)
class EditProfileView(UpdateView):
model = Profile
fields = ['profile_image', 'stories', 'website', 'twitter', 'location']
template_name = 'edit_profile.html'
success_url = reverse_lazy('index')
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super(Creator, self).save(*args, **kwargs)
def index(request):
return render(request, 'index.html')
profile.html:
<div >
<div >
{% comment %} {% for profile in profiles %} {% endcomment %}
<div >
<a href="{{profile.website}}">{{profile.website}}</a>
<a href="{{profile.twitter}}">{{profile.website}}</a>
</div>
{% comment %} {% endfor %} {% endcomment %}
</div>
</div>
<br>
<div >
<div >
<a href="{% url 'editProfile' profile.slug %}" >Create Profile</a>
</div>
</div>
Note:
I have passedprofile.slug
since theEditProfileView
also requires slug to come in route.
Note:
You should not run loop while displaying data with single object.
index.html (success template):
<body>
<h3>Profile updated successfully.</h3>
</body>
edit_profile.html
<body>
<h2>You can edit your profile </h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
</body>
That will successfully update your profile.