Django admin customization

Hi!

I have two models - Buyer(User) and Car.
The Car objects has license number which is unique per instance.

I want to assign multiple car objects to buyers.
I think I may need to create a model looks like this.

class Assignment(models.Model):
	
	buyer = models.OneToOneField(User, related_name='assignment', on_delete=models.CASCADE)
	assigned_cars = models.ManyToManyField(Car, related_name='assignment')

	created = models.DateTimeField(auto_now_add=True)

	class Meta:
		...
		

Then I added the model to admin page so that I can assign cars to buyers.

Here are my problems.

  1. I want to show Car license numbers in the list, currently, it shows car brands as configured by __str__ method

  2. The admin interface to add multiple cars to a user is not convenient.
    (Hold down “Control”, or “Command” on a Mac, to select more than one.)

  3. I want to exclude from the list the cars that were already assigned to other buyers because a car can be assigned to a single buyer only. We cannot sell a car to two or more people.

I am not sure how I can customize django admin to achieve this.
Any help would be appreciated.

Thanks

You don’t need that additional layer for assignments. You can add something like an assigned_to field in your car that is a ForeignKey to User/Buyer.

1 Like

Yes, I understand.
But the problem is I have to add an admin panel where the administrator can assign a list of license plate numbers to a user.

Please post your models completely.

The User model is the one from django.contrib.auth.models.
The Car model.

class Car(models.Model):
    serial_number = models.IntegerField()
    brand = models.CharField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_add=True)
    class Meta:
        ...

@OmidShojaee
Please let me know if you need more but I think these are enough
Thanks

OK I created your scenario on my test environment.

First, you have some typos/errors in your code. Please look at how I defined your models:

from django.db import models
from django.contrib.auth.models import User

# Create your models here.

class Car(models.Model):
    serial_number = models.IntegerField()
    brand = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.serial_number)


class Assignment(models.Model):
    buyer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='Assignment')
    assigned_cars = models.ManyToManyField(Car, related_name='assigned_cars')
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.buyer

Now when I go to my admin site this is what I see:

Screenshot 2021-03-22 010203

I believe this is what you wanted — to display the serial number of each car.

And this one is for when I create a new assignment:

CTRL or COMMAND keys to select more than one car.

Let me know if I missed something.

Well, actually, that’s what I did already and you can read the problems that I want to improve on my initial post.
Please check out those three items that I want to implement.
Thanks

@KenWhitesell
For now, I only have admin panel to assign the cars to a user, no APIs or something else.
And I have to do it on admin panel.
I don’t want to loop over the cars and assign them one by one to the user.
I know it’s a very special case but I need to implement it that way.
Hope you understand this.

Fortunately, the Django Admin provides the facility for you to create a custom form and use it as the admin form. This would let you build the widgets you want in the way you want to do it.

(Note - the behavior of the multi-select is an HTML / standard widget issue, not a Django issue. If you want some other type of behavior for multi-select, you’ll need to implement it yourself using some other widget - perhaps using something from jQuery or some other javascript-based multiselect widget.)

Thank you for your answer!

But I still have more questions.

  1. How can I get rid of cars that were already assigned to users on the list?
  2. __str__ method currently shows car name at the moment which is used in other views.
    I am not sure how I can display serial numbers on this assignment view only

I really appreicate your help on this. This is really what i am not experienced in

You’ll be building a complete custom form. That means that you can customize the select widget to supply whatever entries you want as choices and to format them however you’d like. Build a query that filters out assigned cars and then format that as a “list of tuples” suitable for use as the choices attributed in your widget.

See the docs page and the examples for Widgets to get some ideas.
Also see the queryset attribute in the ModelChoiceField docs for more detailed information.