Currently, I am logged in as an owner and I want to update the fields of customers in the database. But the form does not update or show the details as a placeholder because the user model has extended the customer model and hence, the customer model does not have its own fields. How do I get the instance of the User of the Customer in the UpdateView?/How do I update the customer?
urls.py
urlpatterns = [
path('<int:pk>/update/',CustomerUpdateView.as_view()),
]
views.py
class CustomerUpdateView(OwnerAndLoginRequiredMixin, generic.UpdateView):
template_name = "customer_update.html"
form_class = CustomerModelForm
queryset = Customer.objects.all()
def get_success_url(self):
return "/customers"
models.py
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class User(AbstractUser):
is_owner = models.BooleanField(default=True)
is_agent = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
forms.py
class CustomerModelForm(forms.ModelForm):
class Meta:
model = User
fields = (
'email',
'username',
'first_name',
'last_name',
)
CodePudding user response:
So at this point, I'd have to assume a few things here... Let's say you have a ListView
to render a list of customers.
views.py
file:
class CustomerListView(OwnerAndLoginRequiredMixin, generic.ListView):
template_name = "customer_update.html"
queryset = Customer.objects.all()
context_object_name = 'customers'
urls.py
file:
urlpatterns = [
...
path('customers/', CustomerListView.as_view(), name='customers'),
path('update-customer/<int:pk>/', CustomerUpdateView.as_view(), name='update-customer'),
# You can pass whatever customer related info you wish via url, I'm just using id as a simply demo.
...
]
html
file:
{% for customer in customers %}
# Displaying other related info per customer
# Link to click to update a particular customer profile: passing the customer pk via url
<a href="{% url 'update-customer' customer.pk %}"> Update {{ customer.user.username|title }} Profile </a>
{% endfor %}
Back to the views.py
file:
class CustomerUpdateView(OwnerAndLoginRequiredMixin, generic.UpdateView):
template_name = "customer_update.html"
form_class = CustomerModelForm
# context_object_name = 'customer'
# queryset = Customer.objects.all() # not needed here
# You can use the get_object() on the class to grab the customer object by the pk passed via url
def get_object(self, queryset=None):
customer_pk = self.kwargs.get('pk', None)
return get_object_or_404(Customer, pk=customer_pk)
# Also, you could use the get_context_data() to set the form values before rendering on the page
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
customer = self.get_object() # -> returns a customer object
# creating a dictionary to use to initialize the form: accessing the user information on the customer
data = {
'username': customer.user.username,
'first_name': customer.user.first_name,
'last_name': customer.user.last_name,
'email': customer.user.email,
}
form = self.form_class(initial=data, instance=customer.user) # updated here too
context['form'] = form # -> updating the class view context dictionary
return context
def get_success_url(self):
return "/customers"
Now within the customer_update.html
:
<form method="POST">
<div>
{{ form.username }}
{{ form.email }}
{{ form.first_name }}
{{ form.last_name }}
</div>
<input type="submit" value="Update"/>
</form>
Ideally, that should display the customer's information in the form.
UPDATES
To handle and save the form submission, you can use the post()
on the update-view
. You can add to the CustomerUpdateView
:
# Use the post method to handle the form submission
def post(self, request, *arg, **kwargs):
# Should set the user instance on the form
customer = self.get_object()
form = self.form_class(request.POST, instance=customer.user) # updated here too
if form.is_valid():
form.save()
return redirect('to any path of your choice') # Redirect upon submission if necessary
else:
print(form.errors) # To see the field(s) preventing the form from being submitted
# Passing back the form to the template
return render(request, self.template_name, {'form': form})