I have a question when sending an object to me DetailView
:
class ProfileDetailView(DetailView):
model = Profile
template_name = 'profiles/profile_detail.html'
def get_object(self):
return get_object_or_404(Profile, user__username=self.kwargs['username'])
This would be my model Profile
:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
avatar = models.ImageField(upload_to = custom_upload_to, null = True, blank = True)
biography = models.TextField(null = True, blank = True)
link = models.URLField(max_length = 200, null = True, blank = True)
My first question is, which field am I referring to in this part of the code?: ...,user_username=self...)
Am I referring to username
the model User
field or the user
model field Profile
?
My second question is why is there a reference to this field in this strange way?:user__username
And well, my last question is, how is it that get_object
the dictionary receives the method self.kwargs
? And how is it that the username
user's dictionary is found in that dictionary? I also saw that you could access the pk
object, through the self.kwargs
, but I don't receive the pk
, why is that?
Thanks in advance for your answers!
I'll help you answer and refer you to this page which I always reference for Django Class Based Views . Everything that I will answer you I get from there, it is a matter of interpreting the code and you will see the answer to each question.
Something very incredible about the Django ORM is precisely how it handles "queries" (queries to the database) and one of its characteristics is the way in which it obtains and consults the tables related to the model. In this case, you have a named model
Profile
with a field in its table that has a one-to-one relationship with tableUser
. This logically means that a user has only one profile, and in the same way a profile belongs to only one user.To answer your question, you make two statements, and both are correct. If you are referring to the field
username
ofUser
and at the same time to the fielduser
ofProfile
, why? because when you are going to query the database, normally you want to do aWHERE
and filter the data you want, in this case you want to get a record from your tableProfile
but the parameter you have to do the search in your database does not reference to tablePROFILE
if notUSER
. That is, you have is theusername
user's. In Django this is possible.I explain further, you could consult a profile given a user, with the user's id, in this way:
You could just do it with an object
User
, like this:But also, you could do it by querying the model fields
User
What does that mean? That you can also consult for any other field that belongs to
User
:Django uses the expression
__
when you want to reference fields that belong to a related table. That is, as you can see in the example, neitherusername
, noremail
norpassword
belong to tableProfile
, so I must specify in the query which table they go to. leaving a structure like thisIn the end, this translates into saying this to Django: "Django, fetch me the profile record that, having a relation to the table,
User
has anUser.username
equal to the value that you specify"Another way to do this is the following:
User.objects.get(username=self.kwargs['username']).profile
So answering your question again, YES if you refer to
user
the model fieldProfile
and YES you also refer tousername
the model fieldUser
thanks to the fact that with__
you can do a join.Suddenly I can't get to why, let's just say the people who developed Django figured it out. But it is the way to do it, and it has worked well for everyone so far. As I have had the experience of working with several frameworks and ORMs such as Laravel, WordPress, Waterline, Sequelize and others, it seems to me that Django is the one that best manages queries and joins. It's just a matter of understanding it a little more so that you can see the potential that this has.
If you see the page that I recommend you read, you will see that it
DetailView
is a class, so claiming that itget_object
receivesself.kwargs
is not entirely valid, since itself
is the instance andkwargs
it is a property of that instance. In fact, the place where that property is set is in the methodas_view
, if you read there is a line where it determinesself.kwargs = kwargs
and these kwargs come from the configuration of the urls, so itDetailView
does not fill it, but it receives it somewhere else of Django code that doesn't deserve to be explained, because as I already told you in an answer, It is not necessary to know how Django builds therequest
, that is Django's business and we must trust it, as long as we don't need any kind of metadata of the request.There is a question that I will not be able to answer you and that is the reason why he
username
is reaching you that way. The truth is that it will depend on the configuration of your urls, as I already answered in Duda with UpdateView in Django , the fact that you can receive parameters in the url will depend on your regular expression in the url. I invite you to read your previous question again and see how what you receive in the url works according to the groups in the regular expression. Most likely you don't have apk
because in the urls you don't have something like this:(?P<pk>\d+)
. But if you want, you can attach the code of your urls to help you better answer this point.