User.first_name

How do I obtain the users first name (assuming it’s been populated) for use in a the admin section?

This provides me with the username, then I can register the class in the admin.py to see the user_name. I want to now retrieve the first and/or last name. Not sure if I need to assign the name to a variable, if so what type of variable?

user_name = models.ForeignKey(User, 
on_delete=models.CASCADE, 
default=None, 
null=True, 
blank=True)

You access fields within an object using the “dotted” notation.

For example, if:
a_user = User.objects.get(username="abcdef")
then the first_name field is:
a_user.first_name

If you have a foreign key reference through an object, e.g.

class SomeObject(models.Model):
    user = models.ForeignKey(User, ...)

and you have an instance:
some_object = SomeObject.objects.get(id=1)
then to follow the foreign key relationship, you would use:
first_name = some_object.user.first_name

I appreciate the quick response, but I don’t follow.

class PizzaOrder(models.Model):

  user_name = models.ForeignKey(User,
  on_delete=models.CASCADE,
  default=None,
  null=True,
  blank=True)

I tried both way’s inside the class without success I suspect that’s the problem. I think what I need do is to create a separate class for User attributes that I want to obtain. The information is being used to create a group order. Inside the PizzaOrder class I’m calling user_name but I think I need do this outside the class so that I can obtain the attributes first name and last name or any other attribute I want from django.contrib.auth. Is my thinking correct?

  # Option 1: AttributeError: 'ForeignKey' object has no attribute 'first_name'
  # firstName = user_name.first_name

  # Option 2: NameError: name 'PizzaOrder' is not defined
  # firstName = PizzaOrder.user_name.first_name

We’re going to need more context of the code you’re trying to run.

This is not correct. Any class can retrieve any attributes from any class to which it’s related or can retrieve.

This is also not correct. First name and last name are attributes on the User class. You will retrieve those attributes from an instance of the class (User) not from the module (django.contrib.auth).

When I view PizzaOrder inside my admin I see Pizza orders. I can add a pizza order as an admin by selecting the User name. I’m presented with a drop down and I can select any user on my site. In models.py the model user_name is a ForeignKey pointing to the class User. When I make the user_name selection I would like to get any of the attributes from the user_name. I will provide a first_name field and when I select the user_name from the drop down, I would like the first name to populate, if its there.

I can get the individual first/last names in html tags;

{ user.last_name }
{ user.first_name }

But I would like to see the names populated in the admin section when I need to manually add orders.
Normally a user would provide the order.
The code below works, giving me the user_name but it’s not helpful when creating lists to send to a restaurant. The list will be a group.

class PizzaOrder(models.Model):
  
  user_name = models.ForeignKey(User, 
  on_delete=models.CASCADE, 
  default=None, 
  null=True, 
  blank=True)

  order_Number = models.ForeignKey(GroupOrderNumber,
  on_delete=models.CASCADE,
  default=None,
  null=True,
  blank=True)

  pizzaTopping1 = models.ForeignKey(PizzaTopping, 
  related_name='Topping1', 
  default=6, 
  on_delete=models.CASCADE)
  
  pizzaTopping2 = models.ForeignKey(PizzaTopping,
  related_name='Topping2',
  default=6,
  on_delete=models.CASCADE)
  
  drink = models.ForeignKey(GenericDrink,
  default=2,
  on_delete=models.CASCADE)

Are you talking about pages you have created, or the Django admin?

Ok, what you’re talking about here are known as “chained” or “connected” selection boxes.

This has nothing to do with the models themselves - this is an activity done by JavaScript within the browser. You need some JavaScript that is triggered when the User selection box is updated, makes an AJAX call to the server to retrieve the name, and then use the response to update the other form fields.

Are you talking about pages you have created, or the Django admin?

Django admin.

Ok, what you’re talking about here are known as “chained” or “connected” selection boxes.

This has nothing to do with the models themselves - this is an activity done by JavaScript within the browser. You need some JavaScript that is triggered when the User selection box is updated, makes an AJAX call to the server to retrieve the name, and then use the response to update the other form fields.

Maybe, but is it possible within Django admin? I can do this in html, but I want the first name and last name attributes to populate in Django admin when called.

image

image

Is this image you’re showing here of one page or two?

If it’s of two pages, yes, you can do what you’re trying to do within the admin.

Also, from what you’re saying, is this a page that you’re exposing to the end users? If so, I’m going to strongly suggest you find another way to do what you’re trying to do.

Please read the first paragraph of the official docs and take what it tells you to heart - The Django admin site | Django documentation | Django

Both images are of the Django admin section. They are not exposed to end users unless the user is an admin. I don’t think I’m explaining things correctly. Let me try again.

In the admin section I have registered the class PizzaOrder. Actually the registration is done in admin.py.

@admin.register(PizzaOrder)
class PizzaOrder(admin.ModelAdmin):
  list_display = (
  'user_name',
  # 'firstName',
  'pizzaTopping1',
  'pizzaTopping2',
  'drink',
  'order_Number',
  )
  ordering = ('pizzaTopping1',)
  search_fields = ('pizzaTopping1',)

PizzaOrder has a ForeignKey named user_name. user_name provides the user that submitted the order which is good (and necessary) but I would like to get the users first name and/or last name to see in the list of orders in the admin section. I can get the { user.last_name } or { user.first_name } on the html template but I want to see the users first and/or last name in the admin section.

So in the admin section, as an admin I can manually create an order and assign it to a user. When I do I select the user that is available to me through the dropdown box as a user_name. When I make the selection, I would like to have a field populate with that users first name and/or last name.
That means that I would need to have created a field of what what type exactly? A CharField? Another ForeignKey. If I need another ForeignKey how do I write that;

class ForeignKey(to, on_delete, **options)

as an aside; where do I find the options? I have not been able to find options in the Django docs.

I don’t think a ForeignKey would work because I don’t what to select the users first and or last name. I want it to come from the instance of that user.

firstName = models.ForeignKey(User, **options
on_delete=models.CASCADE)

Not sure if that explains it. Let me know if I need to clarify further.

Is that one page or two?

I answered that in a previous reply. If you’re looking to change a page, after it has been rendered and sent to the browser, you need to do it with JavaScript.

But that’s why I’m asking whether the image is of one page or two. If it’s two pages, then you already have the information from the first page available to you.

What is the code that is creating the page you’ve got titled as “Select pizza order to change”?

Is that one page or two?

Two Pages.

What is the code that is creating the page you’ve got titled as “Select pizza order to change”?

This is the PizzaOrder class I pasted above.

Please read the first paragraph of the official docs and take what it tells you to heart - The Django admin site | Django documentation | Django

I understand what your saying here. I did not intend on building my entire front end around the admin site. Not sure how you came to that conclusion.

Ok, now I see.

In the admin, when you want to traverse a relationship, you need to create a method in your ModelAdmin class to do it.

The key item from the ModelAdmin.list_display docs says that an entry in the list_display can be:

A string representing a ModelAdmin method that accepts one argument, the model instance. For example:

(and then the relevant method follows)

So, you’ve got a couple of different choices:

  • Create a function in your ModelAdmin class that returns the first name and last name as a single string. Specify the name of that function in a new field.

  • Create two separate functions, one for each of first name and last name, adding both functions as fields in list_display.

In either case, these functions are to be named differently from any fields in the tables.

1 Like

I made no such judgement, I just asked the question (the paragraph before what you quoted).

The reason I asked is because it looks like you’re investing a lot of time customizing the admin. When I see that, it’s usually because the individual is trying to use the admin for what I would refer to as routine data entry functions. (Such as taking orders)

It’s a rabbit hole that’s easy to fall into that becomes increasingly difficult to dig your way out of over time.

Now, if that’s not the case, great. If this is only being used for staff maintenance functions, fantastic. That answers my question in the way I would have hoped.

Yep, you hit the nail right on the head. I have been going beyond the pale in customizing the admin.
Hopefully this provides me some benefit before I send meal order requests to my users. I wanted to do as much testing as possible.

Thanks for your patience with my questions.

After some trial and error the solution was painfully simple. I created a method inside the admin.ModelAdmin class of the admin.py

def firstName(self, obj):
    return obj.user_name.first_name

The user_name is a field in the models.Model class of the models.py that is a ForeignKey pointing to User in django.contrib.auth.models. Now what shows up, and what I wanted all this time is the user first name. I really struggle with the docs. What is the admin decorator for? I used the third example;

class PersonAdmin(admin.ModelAdmin):
    list_display = ('upper_case_name',)

    @admin.display(description='Name')
    def upper_case_name(self, obj):
        return ("%s %s" % (obj.first_name, obj.last_name)).upper()

But I didn’t need the display decorator.

That’s correct. The display decorator is not required.

See the docs for the display decorator.

The returned value of last name is not sortable in the admin view. Also I can’t use the last name value for sorting in a filter I’ve created in my view. orderByNumber below works using a ‘user_name’ from the User extended Profile class.

orderByNumber = BostonPizzaOrder.objects.all().filter(order_Number=userSelection).order_by('user_name')

Because the last name in the admin section can’t be sorted, I needed an alternate solution for testing. I retrieve the user last name from the custom Profile I had created at the start of the project.

Here’s the model.

class BostonPizzaOrder(models.Model):
  
  user_name = models.ForeignKey(Profile,   
  on_delete=models.CASCADE,
  default=None, 
  null=True, 
  blank=True)

The docs advise Using a custom user model when starting a project. I created a Profile class when I first started the project but didn’t do much with it.

I would like to use the user_name ForeignKey as a selector that will display the last name in corresponding field.

  1. Can I do this with a CharField and the dot convention?
  2. Do I have to write a function?
  3. Is there a better/standard way?
  4. Can you provide an example of what the syntax might look like?

As written, without additional context, I would say that this statement is not correct.
See about the 10th bullet in the “special cases” section of the list_display docs.

Also effectively incorrect in the absence of further context. (You may not be able to use a value you’re generating for your admin view, but you can order by a related field in a queryset.)

Note: Those two items (a “custom user” class and a “profile” class) are separate, distinct, and complimentary items. You can have a custom user class with or without a profile class, and you can have a profile class with or without a custom user class.

For clarity - you’re looking to have select box for that user_name field show the last_name field as the choices in that select box?

If so, see the iterator docs in the ModelChoiceField section and the corresponding example. (Summary: You would create a custom class to return the string you want represented as the value within the select box.)

As written, without additional context, I would say that this statement is not correct.
See about the 10th bullet in the “special cases” section of the list_display docs.

Here’s a screenshot of what I mean by not sortable. When you click on the USER NAME header Django sorts. LASTNAME and FIRSTNAME don’t have the same ability. Why the difference?

For clarity - you’re looking to have select box for that user_name field show the last_name field as the choices in that select box?

I would like to select the User name and populate a field (named in the screenshot as Last Name) with the Last name from the Class User or Profile.