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.slugsince theEditProfileViewalso 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.
