I want to change the primary key being sent to the update view from the template. Let me explain. Here is my template:
<a href="{% url 'new_url' model_instance.pk %}">
{{ model_instance.username }}
</a>
This model_instance is an instance in a for loop of the context variable model_instances in a list view. This primary key of the model_instance will then be sent to the following view:
class UserUpdateView(generic.UpdateView):
template_name = "leads/update.html"
queryset = User.objects.all()
context_object_name = "user"
form_class = UserUpdateForm
def get_success_url(self):
return reverse("some-url")
However, the problem is that the primary key I am sending to UserUpdateView is the primary key for the model_instance model, not the User model. Moreover, there is no link like one-to-one relationships between the two models. However, there is a similarity. Both of the model_instance and user each have a username field that are the same.
In other words, I need to first retrieve the model_instance.username, and then query the User model to find the user instance with the same username I want to update. At the moment, the UserUpdateView is simply receiving the primary key for a model_instance in the template, which is not what I want. I hope you guys can help me with this issue, and please leave any questions you have. Thank you.
It's not intuitive enough but yes it is possible. It's also good to mention that you define a queryset attribute in the view, if you want update only one object then it's not necessary.
You can override the get_object method to do this :
class UserUpdateView(generic.UpdateView):
template_name = "leads/update.html"
# queryset = User.objects.all()
context_object_name = "user"
form_class = UserUpdateForm
def get_success_url(self):
return reverse("some-url")
def get_object(self):
# Here w'll retrieve the correct object to update
# First we retrieve the username of the model_instance
model_instance = ModelInstance.objects.get(pk=self.kwargs['pk'])
username = model_instance.username # Retrieve the username
# After, retrieve the user with username=model_instance.username
# Normally, the username must be unique per model_instance and per user. If not an error can be trowed.
user = User.objects.get(username=username)
# If username is not unique, try this approach
# user = User.objects.filter(username=username).first()
# Return the user object
return user
This template link :
<a href="{% url 'new_url' model_instance.pk %}">
{{ model_instance.username }}
</a>
will now point out the user to update, not the model_instance.
More about get_object
Since model_instance and user have the same username, you could pass in the model_instance.username when generating the url and change your UpdateView to specify slug_field = "username". You would also have to change your urlconfig to use "slug" instead of "pk" or add slug_url_kwarg = "pk" .
<a href="{% url 'new_url' model_instance.username %}">
{{ model_instance.username }}
</a>
class UserUpdateView(generic.UpdateView):
template_name = "leads/update.html"
queryset = User.objects.all()
context_object_name = "user"
form_class = UserUpdateForm
slug_field = "username"
slug_url_kwarg = "pk"
def get_success_url(self):
return reverse("some-url")