Django 1.11 admin form add search box to oneToOne field - django

I have a user, admin and employee models, both employee and admin are related to the user model with a oneToOne field what i would like to do is in the admin form i have one field "user"
instead of having a drop down field with all users i would like to have a search box so that when i search for a specific user i find him and choose him to be an admin.
how?
i also tried to add user's fields to admin's form but i couldn't
i tried the inline thing, the parent_link in the admin's model... but i couldn't find a solution
Now i would like to minimise the search through the long users list by adding a search box to the field

I have solved this type of problem using django-ajax-selects package. Hope this will help you.
app/admin.py:
from ajax_select import register, LookupChannel
#register('users')
class UsersLookup(LookupChannel):
model = User
def get_query(self, q, request):
return self.model.objects.filter(username__icontains=q)
class EmployeeAdminForm(forms.ModelForm):
user = AutoCompleteSelectField('users', required=False,
help_text=None)
class Meta:
model = Employee
fields = '__all__'
settings.py
AJAX_LOOKUP_CHANNELS = {
'users' : {'model': 'auth.user', 'search_field': 'username'},
}

Use django's raw_id_fields. With that you can declare a foreign key object searchable.

Related

Django display list of ForeingKey relationship

I'm using django 2 and python 3.
In my model I have Users that can own a list of Applications. Applications can have only one Owner.
I used a ForeingKey like so:
class User(AbstractUser):
# nothing interresting for this question here
pass
class StoreApplication(models.Model):
owner = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="applications"
)
Now I would like to list the User's applications in the User's admin page, like a list of application names, just readonly stuff. Not in the list view, in the edit view.
I'm aware of InlineModelAdmin and it does not seem to resolve my issue, as it includes the whole Application forms for each of the user's application.
If I try to reference the field as "applications" in my user admin:
class UserAdmin(admin.ModelAdmin):
list_display = ("username", )
fieldsets = (
("Général", {
"fields": ("username", "applications", )
}),
)
An error occurs:
Unknown field(s) (applications) specified for User. Check fields/fieldsets/exclude attributes of class UserAdmin.
You could add a method to the UserAdmin that returns all the applications as a comma separated list. I'm going to assume there is a CharField on the StoreApplication model that names the object (name)
def get_applications(self, obj):
return ', '.join([app.name for app in obj.applications])
# set the short_description to how you want that field displayed in admin
get_applications.short_description = 'Applications'
Then just add get_applications to fields and readonly_fields

list_display in admin behave nothing

This is my github repo Inout. I am learning django and i worked Very very simple django registration & login system.
My question is:
How to list all the usernames in admin using list_display. But nothing display in admin panel. May i know why ?
Inside my working code:
# models.py
username = models.OneToOneField(User)
first_name = models.CharField(max_length=100)
# admin.py
class SignupAdmin(admin.ModelAdmin):
list_display = ['username']
admin.site.register(Signup, SignupAdmin)
Information for you Reference :
if i am using list_filter in admin i can see all the username in the filter panel
Then if i am accessing this page http://127.0.0.1:8000/admin/system/signup/
Select signup to change
0 signups
And also if i am accessing this page http://127.0.0.1:8000/admin/frontend/profile/add/ i can see the drop down of username shows all the username i registered before.
What i missing ? or can somebody clone my repo and see yourself.
Are you sure it's not working correctly? list_display is supposed to take a tuple/list of fields and then display those fields as columns of the main table like in the picture shown below taken from the django admin documentation, where each entry in the main table has a username, email address, first name, last name, staff status. This would be created by
list_display = ['username', 'email', 'first_name', 'last_name', 'is_staff']
in a ModelAdmin for the built in User model (taken from django.contrib.auth.models). The side-column on the right side (with the label "Filter") is populated only when you define fields under list_filter.
Note if you only defined one field, and your model has a __unicode__ function that returns the username, you will not see a significant difference with just adding list_display = ('username',). I suggest you try list_display = ('username', 'first_name',). In this case, for every SignUp you will see two columns in the main table -- one with the username and one with the first_name.
EDIT
You have two errors.
First, you don't seem to have created any SignUp objects anywhere. Before the admin change list will display any entries, you must create some entries.
Second, your __unicode__ method of your SignUp model refers to non-existent fields (self.user is never defined -- in your SignUp class you used username = models.OneToOneField(User)
, hence you refer to it as username) and furthermore it doesn't return a unicode string as required.
Try:
def __unicode__(self):
if self.username:
return unicode(self.username)
then create some SignUp and then it will work. Again, the list_display part was working perfectly.

Django Customizing authentication user results in 2 fields in admin

I've followed https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#extending-the-existing-user-model to add a ManyToMany field for what games a user has played.
class Profile(models.Model):
""" Extended authentication profile storing specific info """
user = models.OneToOneField(User)
owned = models.ManyToManyField(OwnedStruct)
then add to admin by the following
class ProfileInline(admin.StackedInline):
""" Show profile inline with user """
model = Profile
verbose_name_plural = 'profile'
class UserProfileAdmin(UserAdmin):
""" Add inline to User """
inlines = (ProfileInline,)
...
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
In the database things look fine, but in the admin I see two fields representing the ManyToMany OwnedStruct. Before messing with the user, it shows the first as "Profile #1" and the second as "Profile #2". After selecting some options from Profile 1's M2M and clicking save, it appears to update that field correctly. If I update Profile#2, it does not save or work or appear to change anything. I'd expect it to only show one. What could cause two Profiles?
If I understand correctly the problem is that for some reason django admin doesn't care about OneToOneField and create more than one inline forms for the Profile. You can try to fix that with adding max_num = 1 to your ProfileInline class.
It must look something like:
class ProfileInline(admin.StackedInline):
""" Show profile inline with user """
model = Profile
max_num = 1
verbose_name_plural = 'profile'

Accessing a model variable in Django

Obviously I am new to Django, because I would assume this is relatively simple.
Lets say in my models.py I created a model "User", with two fields, a "username" and a "email" field. In a form called "UserForm", I want to access a list of all the "username"s in the "User" model. This list would then be used to populate a dropdown menu using Select.
I feel like this should be really easy, and I have been looking for some simple way to do it. I can find lots of ways that aren't all inclusive (ie filter(username = "Joe")), but I can't find one that will list all the users.
Any help would be greatly appreciated.
You're looking for a ModelChoiceField. Its queryset property can be populated from an ORM call, getting you all of the Users. Have a look at the section Creating Forms from Models in the docs for more information.
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = # Your model here
def __init__(self, *args, **kwargs):
self.fields['user'] = forms.ModelChoiceField(queryset=User.objects.all())
ForeignKey fields will be automatically shown as ModelChoiceFields, but you can always override the choices if you need.

Django admin: search for foreign key objects rather than <select>?

My model looks like this:
class Asset(models.Model):
serial_number = models.CharField(max_length=100, unique=True)
asset_tag = models.CharField(max_length=100, unique=True)
class WorkOrder(models.Model):
asset = models.ForeignKey(Asset)
Essentially, a work order is submitted and then an admin assigns an asset to the work order. The asset_tag field is a barcode that we can scan in. When editing the work order in the Django admin, by default the asset field is displayed as a <select> widget. What we want to be able to do is have a search field so that we can scan the asset tag and then search for the right asset in the DB to associate with the work order.
I know you can customize the Django admin foreign key to a hard coded query, but I can't figure out how to get it so it does a search based on a field on the admin page.
Did you take a look at raw_id_fields?
It should be pretty to close to what you're after.
If you are using Django >= 2.0, you can take advantage of a feature called autocomplete_fields. You must define search_fields on the related object’s ModelAdmin because the autocomplete search uses it.
Since you have a ForeignKey relationship to Asset in WorkOrder, in the admin.py of your app add the following:
from django.contrib import admin
#admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
search_fields = ["serial_number", "asset_tag"]
#admin.register(WorkOrder)
class WorkOrderAdmin(admin.ModelAdmin):
autocomplete_fields = ["asset"]
Add the fields you want to use for searching to search_fields, and add define autocomplete_fields as shown in the code above.
Now you can use the autocomplete_fields from django 2.0.
It's quite neat.