Holla ppl. Im new in django and trying my best , but at this point im stuck and need some help.
The thing is: i cant update my user-profile via template. when i do some changes --- in console i can see POST, then i get redirect by "success_url". no errors shown.but new data is not saved.
django 1.11.4
here my codes:
Models:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(blank=True)
location = models.CharField(max_length=30, blank=True)
bio = models.TextField(max_length=500, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Views:
class RegisterView(CreateView):
template_name = "registration/register.html"
form_class = RegisterForm
success_url = '/'
def dispatch(self, *args, **kwargs):
# if self.request.user.is_authenticated():
# return redirect("/logout")
return super(RegisterView, self).dispatch(*args, **kwargs)
class ProfileUpdateView(UpdateView):
model = Profile
form_class = ProfileForm
template_name = 'profiles/profile-detail-update.html'
success_url = '/'
def get_object(self, **kwargs):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(User, username__iexact=username)
Forms
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username',)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=True)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('avatar', 'location', 'bio', 'active',)
URL
url(r'^(?P<username>[\w-]+)/$', ProfileUpdateView.as_view(), name='update'),
Template:
{% extends 'base.html' %}
{% block content %}
<p>name: {{ user.username }}</p>
<p>location: {{ user.profile.location }}</p>
{% if user.profile.avatar %}
<img style="width: 200px" src="{{ user.profile.avatar.url }}"/>
{% endif %}
<hr/>
{% include 'snippets/form.html' %}
{% endblock %}
Included snippet:
<div class="form pt-2">
{% if form.errors.non_field_errors %}
{{ form.errors.non_field_errors }}
{% endif %}
<form method='POST' action='' enctype='multipart/form-data'> {% csrf_token %}
{{ form.as_p }}
<button class='btn btn-success' type='submit'>Save</button>
<button onclick="window.history.back();" class="btn btn-danger" type="button">Go back</button>
</form>
</div>
SOS.
In your ProfileUpdateView you are passing an User instance to the form, instead of a Profile instance:
class ProfileUpdateView(UpdateView):
# ...
def get_object(self, **kwargs):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(Profile, user__username__iexact=username)
Related
I recently started learning django and was making a CRM.
models.py:
class Complaint(models.Model):
SOURCE_CHOICES=(
('email','E-mail'),
('call','Call'),
('ticket','Ticket')
)
store_name=models.CharField(max_length=20)
store_contact_no=models.IntegerField(max_length=10)
store_id=models.CharField(max_length=7)
source=models.CharField(choices=SOURCE_CHOICES, max_length=10)
agent=models.ForeignKey("Agent", null = True, blank = True, on_delete=models.SET_NULL)
category=models.ForeignKey("Category", related_name="complaints", null = True, blank = True, on_delete=models.SET_NULL)
description = models.TextField()
customer = models.ForeignKey("Customer", null = True, blank = True, on_delete=models.SET_NULL)
def __str__(self):
return f"{self.store_name} {self.store_id}"
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
forms.py
class CustomerComplaintForm(forms.ModelForm):
class Meta:
model = Complaint
fields = (
'store_name',
'store_id',
'store_contact_no',
'description',
)
views.py
class
CustomerComplaintCreateView(OwnerCustomerAndLoginRequiredMixin,
generic.CreateView):
template_name = "customercomplaint_create.html"
form_class = CustomerComplaintForm
def get_success_url(self):
return "/complaints"
def form_valid(self, form):
complaint = form.save(commit=False)
complaint.Customer = self.request.user.username
complaint.source = 'ticket'
complaint.save()
return super(CustomerComplaintCreateView,
self).form_valid(form)
html template:
{% extends "base.html" %}
{% load tailwind_filters %}
{% block content %}
<div class="max-w-lg mx-auto">
<a class="hover:text-blue-500" href="/complaints">Go back to complaints </a>
<div class="py-5 border-t border-gray-200">
<h1 class="text-4xl text-gray-800"> Create a new complaint </h1>
</div>
<form method='post' class="mt-5">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="w-full bg-blue-500 text-white hover:bg-blue-600 px-
3 py-2 rounded-md">Create</button>
</form>
</div>
{% endblock content %}
mixins.py
class OwnerCustomerAndLoginRequiredMixin(AccessMixin):
"""Verify that the current user is authenticated and is an owner or customer"""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_owner and not request.user.is_customer:
return redirect("/complaints")
return super().dispatch(request, *args, **kwargs)
The problem here is that, the source field gets filled in the database with Ticket as intended. But the 'Customer' field is not populated with the username. 'Self.request.user.username' is not the problem here as the username is being printed correctly in the console.
The issue is complaint.Customer = self.request.user.username, you're trying to assign a username to a supposedly Customer object. Here's an approach you could take to solve the issue though.
Within the views.py file, the view class.
You could get the customer object and then assign it to the customer field on the complaint object.
from django.shortcuts import get_object_or_404
def form_valid(self, form):
complaint = form.save(commit=False)
customer = get_object_or_404(Customer, user=self.request.user) # recommended
# or
# customer = get_object_or_404(Customer, user__username__iexact=self.request.user.username)
if customer:
# Here on your model you have a lowercase `c` for the customer field, not 'C`
complaint.customer = customer # -> This will assign the customer object, "FK".
complaint.source = 'ticket'
complaint.save()
return super(CustomerComplaintCreateView, self).form_valid(form)
That should work.
this must be the User not the user name
Because Cutomer is User object not only the Uesrname
def form_valid(self, form):
complaint = form.save(commit=False)
complaint.Customer = self.request.user
complaint.source = 'ticket'
complaint.save()
I am not that experienced writing Python/Back-end, but trying to improve. In development/localserver I am trying to create a password reset form... but I got the following error when accessing the link from the forgot password email - and before that the password was not saving:
init() missing 1 required positional argument: 'user'
forms.py (almost copy/paste from Django's form; minor changes)
class ResetPasswordForm(SetPasswordForm):
error_messages = {
'password_mismatch': static_textLanguage['page_user_passwordReset_alert_passwordNotMatch'],
'password_empty': static_textLanguage['global_alert_mandatoryField'],
'minimum_length': static_textLanguage['global_alert_minCharacters_password'],
}
new_password1 = forms.CharField(
required=False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordA',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
new_password2 = forms.CharField(
required = False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordB',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
def __init__(self, user, *args, **kwargs):
self.user = user
super(ResetPasswordForm, self).__init__(user, *args, **kwargs)
def clean_new_password1(self):
password1 = self.cleaned_data.get('new_password1')
if password1 == '' or password1 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
elif len(password1) < 8:
raise forms.ValidationError(self.error_messages['minimum_length'], code='password_too_short')
return password1
def clean_new_password2(self):
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password2 == '' or password2 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
if password1 and password2:
if password1 != password2:
raise ValidationError(self.error_messages['password_mismatch'], code='password_mismatch')
password_validation.validate_password(password2, self.user)
return password2
def save(self, commit=True):
password = self.cleaned_data["new_password1"]
self.user.set_password(password)
if commit:
self.user.save()
return self.user
views.py
class UserPasswordResetView(auth_views.PasswordResetConfirmView):
template_name = '../frontend/templates/frontend/templates.user/template.page_passwordReset.html'
form_class = ResetPasswordForm
post_reset_login = True
success_url = reverse_lazy('page_userLoginPrivate')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.user
return kwargs
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if self.validlink:
context.update({
'validlink': True,
'form': self.form_class(),
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
else:
context.update({
'validlink': False,
'form': None,
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
return context
template.html (for purpose of this exercise .html was simplified)
<div class="wrapper_page_userPasswordReset">
{% if validlink %}
<form id="page_userPasswordReset_content_form" class="page_userPasswordReset_content_form" method="post" novalidate>
{% csrf_token %}
<div class="global_component_input_box_container">
{{ form.new_password1}}
</div>
<div id="page_userPasswordReset_input_passwordA_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<div class="global_component_input_box_container">
{{ form.new_password2}}
</div>
<div id="page_userPasswordReset_input_passwordB_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<button type="submit" id="page_userPasswordReset_content_form_button_submit" class="global_component_button button_background_green">{{ static_json_text.global_button_submit }}</button>
</form>
{% else %}
<button id="page_userPasswordReset_button_forgotPassword" class="global_component_button button_background_green">{{ static_json_text.page_user_passwordReset_notValidLink_button }}</button>
{% endif %}
</div>
django
The error most likely happens because you defined user as positional argument (def __init__(self, user, *args, **kwargs):), but you pass the variable as a keyword argument (kwargs['user'] = self.user).
Instead of your code:
class ResetPasswordForm(SetPasswordForm):
...
def __init__(self, user, *args, **kwargs):
self.user = user
...
try changing it to this (so that the ResetPasswordForm looks for the user inside kwargs):
class ResetPasswordForm(SetPasswordForm):
...
def __init__(self, *args, **kwargs):
self.user = kwargs['user']
...
I am having 2 issues, one if you submit and click back and then submit again it duplicates the instance in the database - in this case Household. In addition it is saving the parent 'Household' without the child 'Applicants' despite me setting min_num=1
can someone point me in the right direction to resolve this issue.
Many thanks in advance
class Application(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
application_no = models.CharField(max_length=100, unique=True, default=create_application_no)
created_date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
class HouseHold(models.Model):
name = models.CharField(max_length=100)
application = models.ForeignKey(Application, on_delete=models.CASCADE)
no_of_dependents = models.PositiveIntegerField(default=0)
class Applicant(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
household = models.ForeignKey("HouseHold", on_delete=models.CASCADE)
forms.py
class ApplicationForm(ModelForm):
class Meta:
model = Application
fields = (
"name",
)
class ApplicantForm(ModelForm):
class Meta:
model = Applicant
fields = [
"household",
"first_name",
"last_name"
]
class HouseHoldForm(ModelForm):
class Meta:
model = HouseHold
fields = [
'name',
'application',
'no_of_dependents'
]
def __init__(self, application_id=None, *args, **kwargs):
super(HouseHoldForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'House Hold Name'
if application_id:
self.fields['application'].initial = application_id
self.fields['application'].widget = HiddenInput()
ApplicantFormset = inlineformset_factory(
HouseHold, Applicant, fields=('household', 'first_name', 'last_name'), can_delete=False, extra=1, validate_min=True, min_num=1)
views.py
class HouseHoldCreateView(LoginRequiredMixin, generic.CreateView):
model = models.HouseHold
template_name = "households/household_create.html"
form_class = HouseHoldForm
def get_parent_model(self):
application = self.kwargs.get('application_pk')
return application
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.POST:
context['application'] = models.HouseHold.objects.filter(application_id=self.kwargs['application_pk']).last()
context['house_hold_formset'] = ApplicantFormset(self.request.POST, instance=self.object)
else:
context['application'] = models.Application.objects.get(id=self.kwargs['application_pk'])
context['house_hold_formset'] = ApplicantFormset()
return context
def get_form_kwargs(self):
kwargs = super(HouseHoldCreateView, self).get_form_kwargs()
print(kwargs)
kwargs['application_id'] = self.kwargs.get('application_pk')
return kwargs
def form_valid(self, form):
context = self.get_context_data()
applicants = context['house_hold_formset']
with transaction.atomic():
self.object = form.save()
if applicants.is_valid():
applicants.instance = self.object
applicants.save()
return super(HouseHoldCreateView, self).form_valid(form)
def get_success_url(self):
if 'addMoreApplicants' in self.request.POST:
return reverse('service:household-create', kwargs={'application_pk': self.object.application.id})
return reverse('service:household-list', kwargs={'application_pk': self.object.application.id})
I had a similar problem, I solved it by adding the post() method to the view. The example is an UpdateView but the usage is the same.
(the indentation is not correct but that's what stackoverflow's editor let me do, imagine all methods are 4 spaces to the right)
class LearnerUpdateView(LearnerProfileMixin, UpdateView):
model = User
form_class = UserForm
formset_class = LearnerFormSet
template_name = "formset_edit_learner.html"
success_url = reverse_lazy('home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
learner = User.objects.get(learner=self.request.user.learner)
formset = LearnerFormSet(instance=learner)
context["learner_formset"] = formset
return context
def get_object(self, queryset=None):
user = self.request.user
return user
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
user = User.objects.get(learner=self.get_object().learner)
formsets = LearnerFormSet(self.request.POST, request.FILES, instance=user)
if form.is_valid():
for fs in formsets:
if fs.is_valid():
# Messages test start
messages.success(request, "Profile updated successfully!")
# Messages test end
fs.save()
else:
messages.error(request, "It didn't save!")
return self.form_valid(form)
return self.form_invalid(form)
Keep in mind that to save the formset correctly you have to do some heavy lifting in the template as well. I'm referring to the hidden fields which can mess up the validation process. Here's the template corresponding to the view posted above:
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ learner_formset.management_form}}
{% for form in learner_formset %}
{% if forloop.first %}
{% comment %} This makes it so that it doesnt show the annoying DELETE checkbox {% endcomment %}
{% for field in form.visible_fields %}
{% if field.name != 'DELETE' %}
<label for="{{ field.name }}">{{ field.label|capfirst }}</label>
<div id="{{ field.name }}" class="form-group">
{{ field }}
{{ field.errors.as_ul }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% for field in form.visible_fields %}
{% if field.name == 'DELETE' %}
{{ field.as_hidden }}
{% else %}
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
<input class="btn btn-success" type="submit" value="Update"/>
Additional reading :
https://medium.com/#adandan01/django-inline-formsets-example-mybook-420cc4b6225d
Save formset in an UpdateView
Inspired by Beikini
I have solved it using the create View
class HouseHoldCreateView(LoginRequiredMixin, generic.CreateView):
model = HouseHold
template_name = "households/household_create3.html"
form_class = HouseHoldForm
def get_parent_model(self):
application = self.kwargs.get('application_pk')
return application
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.POST:
context['application'] = HouseHold.objects.filter(
application_id=self.kwargs['application_pk']).last()
context['house_hold_formset'] = ApplicantFormset(self.request.POST)
else:
context['application'] = Application.objects.get(id=self.kwargs['application_pk'])
context['house_hold_formset'] = ApplicantFormset()
return context
def get_form_kwargs(self):
kwargs = super(HouseHoldCreateView, self).get_form_kwargs()
kwargs['application_id'] = self.kwargs.get('application_pk')
return kwargs
def form_valid(self, form):
context = self.get_context_data()
applicants = context['house_hold_formset']
application_id = self.kwargs['application_pk']
household_form = self.get_form()
if form.is_valid() and applicants.is_valid():
with transaction.atomic():
self.object = form.save()
applicants.instance = self.object
applicants.save()
messages.success(self.request, 'Applicant saved successfully')
return super(HouseHoldCreateView, self).form_valid(form)
else:
messages.error(self.request, 'please add an applicant to the household')
return self.form_invalid(form)
def get_success_url(self):
return reverse('service:household-list', kwargs={'application_pk': self.object.application.id})
I have extending user profile with profile model and create an post_save signal.
I works well on user creation but seems that there is an issue on update. When I want to update I have messages saying user and email already exists in data table. So nothing is updated. and and send back to Register page but should go to edit_profile page
My model.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from authenticate.thumbs import ImageWithThumbsField # transforme les images en thumbs
import os
def image_name(instance, filename):
extension = filename.split('.')
extension = extension[-1]
return 'avatars/{}.{}'.format(instance.user.pk, extension)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = ImageWithThumbsField(upload_to=image_name, blank=True) # transforme les images en thumbs
bio = models.CharField(max_length=100, blank=True)
location = models.CharField(max_length=30, blank=True, default='Please fill in info')
birth_date = models.DateField(null=True, blank=True)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
My forms.py:
class UniqueUserEmailField(forms.EmailField):
"""
An EmailField which only is valid if no User has that email.
"""
def validate(self, value):
super(forms.EmailField, self).validate(value)
try:
User.objects.get(email = value)
raise forms.ValidationError("Email already exists")
except User.MultipleObjectsReturned:
raise forms.ValidationError("Email already exists")
except User.DoesNotExist:
pass
class SignUpform(UserCreationForm):
"""
Extends the built in UserCreationForm in several ways:
* Adds an email field, which uses the custom UniqueUserEmailField,
that is, the form does not validate if the email address already exists
in the User table.
* The username field is generated based on the email, and isn't visible.
* first_name and last_name fields are added.
* Data not saved by the default behavior of UserCreationForm is saved.
* add forms control from Bootstrap to improve form UX
"""
email = forms.EmailField(required= True, label='', max_length=100, widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Email address' }))
first_name = forms.CharField(label='',max_length=100, widget=forms.TextInput(attrs={'placeholder': 'First Name', 'class': 'form-control'}))
last_name = forms.CharField(label='',max_length=100,widget=forms.TextInput(attrs={'placeholder': 'Last Name', 'class': 'form-control'}))
class Meta:
model = User
fields = ('email', 'username', 'first_name', 'last_name', 'password1', 'password2',)
def __init__(self, *args, **kwargs):
super(SignUpform, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['class'] = 'form-control'
self.fields['password1'].widget.attrs['class'] = 'form-control'
self.fields['password2'].widget.attrs['class'] = 'form-control'
# change labels
self.fields['username'].label = ''
self.fields['username'].help_text = '<span class="form-text text-muted"><small>Required.</small></span>'
self.fields['email'].help_text = '<span class="form-text text-muted"><small>Required.</small></span>'
self.fields['password1'].label = ''
self.fields['password1'].help_text = '<ul class="form-text text-muted small">' \
'<li>Your password cannot be too similar to your other personal information.</li>' \
'<li>Your password must contain at least 8 characters.</li>' \
'<li>Your password cannot be a commonly used password.</li>' \
'<li>Your password cannot be entirely numeric.</li>' \
'</ul>'
self.fields['password2'].label = ''
self.fields['password2'].help_text = '<span class="form-text text-muted"><small>Enter the same password as before, for verification.</small></span>'
self.fields['username'].widget.attrs['placeholder'] = 'User Name'
self.fields['password1'].widget.attrs['placeholder'] = 'password'
self.fields['password2'].widget.attrs['placeholder'] = 'confirm password'
def clean_email(self):
# Get the email
email = self.cleaned_data.get('email')
# Check to see if any users already exist with this email as a username.
try:
match = User.objects.get(email=email)
print("ok")
except User.DoesNotExist:
# Unable to find a user, this is fine
return email
# A user was found with this as a username, raise an error.
raise forms.ValidationError('This email address is already in use.')
class EditUseform(UserChangeForm):
class Meta:
model = User
fields = ('email', 'username', 'first_name', 'last_name', 'password',)
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('avatar', 'bio', 'location', 'birth_date')
widgets = {
'birth_date': DatePickerInput(), # default date-format %m/%d/%Y will be used
}
My views.py:
def register_user(request):
if request.method == 'POST':
form = SignUpform(request.POST)
profile_form = ProfileForm(request.POST, request.FILES)
if form.is_valid() and profile_form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(request, username=username, password=password)
# modify existing profile
profile = Profile.objects.get(user=user.pk)
profile.avatar = profile_form.cleaned_data['avatar']
profile.bio = profile_form.cleaned_data['bio']
profile.location = profile_form.cleaned_data['location']
profile.birth_date = profile_form.cleaned_data['birth_date']
profile.save()
login(request, user)
messages.success(request, 'You are registered')
# redirect to a succes page
return redirect('home')
else:
form = SignUpform()
profile_form = ProfileForm()
context = {'form': form,
'profile_from': profile_form, }
return render(request, 'register.html', context)
def edit_profile(request):
if request.method == 'POST':
form = EditUseform(request.POST, instance=request.user)
profile_form = ProfileForm(request.POST, instance=request.user.profile)
if form.is_valid() and profile_form.is_valid():
form.save()
# modify existing profile
profile_form.save()
messages.success(request, _('Your profile was successfully updated!'))
# redirect to a succes page
return redirect('edit_Profile')
else:
form = EditUseform(instance=request.user)
profile_form = ProfileForm(instance=request.user.profile)
context = {'form': form,
'profile_from': profile_form, }
return render(request, 'edit_Profile.html', context)
My Edit_Profille.html:
{% extends 'base.html' %}
<!---- datepicker ---->
{% block extrahead %}
{{ profile_from.media }}
{% endblock %}
<!-------->
{% block content %}
<h2 class="text-center">Edit user</h2>
<div class="col-md-6 offset-md-3">
<form method="POST" action="{% url 'register' %}" enctype="multipart/form-data">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-warning alert-dismissable" role="alert">
<button class="close" data-dismiss="alert">
<small><sup>x</sup></small>
</button>
<p>Your form has errors:</p>
{% for field in form %}
{% if field.errors %}
{{ field.errors }}
{% endif %}
{% endfor %}
</div>
{% endif %}
{{ form.as_p }}
{{ profile_from.as_p }}
<input type="submit" value="register" class="btn btn-primary">
</form>
{% endblock %}
I created a form to update a User's profile, however when I run it, there are no errors, but when I try to open up the page, the header appears but the UpdateBioForm does not appear. Secondly, I was wondering how you would create a large textbox to store someone's biography.
Models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
biography = models.CharField(max_length = 255, default = '')
city = models.CharField(max_length=100, default = '')
website = models.URLField(default='')
image = models.ImageField(upload_to='profile_image', blank=True)
def setdefault(self, default_path='/profile_image/Default.jpg'):
if self.image:
return self.image
return default_path
def __str__(self):
return self.user.username
Forms.Py
class UpdateBioForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = (
'biography',
'city',
'website'
)
def save(self, commit=True):
savedBio = super(UpdateBioForm, self).save(commit=False)
savedBio.biography = self.cleaned_data['biography']
savedBio.city = self.cleaned_data['city']
savedBio.website = self.cleaned_data['website']
if commit:
savedBio.save()
return savedBio
Views.py
def update_bio(request):
if request.method == 'POST':
form = UpdateBioForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('/')
else:
form = UpdateBioForm(instance=request.user)
args = {'form':form}
return render(request, 'accounts/update_bio.html')
urls.py
url(r'^profile/updatebio/$',views.update_bio, name='update_bio'),
update_bio.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<h1>Update Biography</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
</div>
{% endblock %}
You are not passing any context to your render() method - you define args but don't do anything with that variable. Change it to:
args = {'form':form}
return render(request, 'accounts/update_bio.html', context=args) # <-- You're missing context