Opened 9 years ago

Closed 9 years ago

Last modified 8 years ago

#3345 closed (invalid)

Admin Search Fields From Related Models

Reported by: rfreitag@… Owned by: adrian
Component: contrib.admin Version:
Severity: Keywords:
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description (last modified by ubernostrum)

I'm trying to in the Admin Change List Form have the ability to search records via information from a related model.

Example
When in case_files I would like to search by Company Name, this information is stored in a separate object.

Can this be possible? Below is a sample of the models.py

Regards

class company_record(models.Model):
    midas_number = models.CharField(maxlength=10, verbose_name='Midas Number')
    company_name = models.CharField(maxlength=200, verbose_name='Company Name')
    midas_parent = models.CharField(maxlength=10, verbose_name='Midas Parent Member Number')
    parent_name = models.CharField(maxlength=200, verbose_name='Parent Company Name')
    company_status = models.CharField(maxlength=100, verbose_name='Member Current Status')
    company_cat = models.CharField(maxlength=10, verbose_name='Company Category')
    def __str__(self):
         return self.midas_number + " - " + self.company_name
    class Admin:
        pass
        list_display = ('midas_number', 'company_name', 'midas_parent', 'parent_name', 'company_status', 'company_cat')
        list_display_links = ('midas_number', 'company_name')
	list_filter = ('company_cat', 'company_status')
        search_fields = ['company_name']
    class Meta:
	 verbose_name = "Company Record"


class case_file(models.Model):
    midas_number_id = models.AutoField(primary_key=True)
    midas_number = models.ForeignKey(company_record, edit_inline=models.STACKED, num_in_admin=1, verbose_name="Company Name")
    fileid = models.CharField(maxlength=10, core=True, primary_key=True, verbose_name='File ID')
    file_state = models.CharField(maxlength=3, core=True, verbose_name='State')
    file_status = models.CharField(maxlength=10, core=True, verbose_name='File Current Status')
    file_open_date = models.DateField('File Open Date', core=True)
    file_close_date = models.DateField('File Close Date', core=True)
    owning_officer = models.CharField(maxlength=200, core=True, verbose_name='"Owning" Officer')
    owning_dept = models.CharField(maxlength=200, core=True, verbose_name='"Owning" Department')
    nature_of_matter = models.CharField(maxlength=200, core=True, verbose_name='Nature Of Matter')
    destroy_date = models.DateField('Destroy Date', core=True)
    purchase_order = models.CharField(maxlength=50, core=True, verbose_name='Purchase Order#')
    document_desc = models.CharField(maxlength=200, core=True, verbose_name='Description of Document')

    class Admin:
	fields = (
		  ('File Status Details', {'fields': ('midas_number', 'fileid', 'file_state', 'file_status', 'file_open_date', 'file_close_date', 'destroy_date')}),
		  ('File Details', {'fields': ('owning_officer', 'owning_dept', 'nature_of_matter', 'purchase_order', 'document_desc')}),
		 )
	list_select_related = True
        search_fields = ['fileid', 'owning_officer', 'midas_number_id']
        list_display = ('midas_number', 'fileid', 'owning_officer', 'owning_dept', 'document_desc', 'file_status' )
	list_display_links = ('midas_number', 'fileid')
	list_filter = ('owning_officer', 'owning_dept', 'nature_of_matter', 'file_status', 'file_open_date' )

    class Meta:
	    verbose_name = "Case File"

Change History (8)

comment:1 follow-up: Changed 9 years ago by SmileyChris

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Design decision needed
  • Version 0.95 deleted

In my opinion, this is a bit outside of what Admin is trying to provide. But I'll let someone else decide that.

On a side note, thanks for the ticket but it didn't really clarify anything by pasting in your entire model - especially without formatting. The "Preview" button is there for a reason ;)

comment:2 Changed 9 years ago by ubernostrum

  • Description modified (diff)

(fixing code formatting in original ticket)

comment:3 in reply to: ↑ 1 Changed 9 years ago by rfreitag@…

Replying to SmileyChris:

In my opinion, this is a bit outside of what Admin is trying to provide. But I'll let someone else decide that.

On a side note, thanks for the ticket but it didn't really clarify anything by pasting in your entire model - especially without formatting. The "Preview" button is there for a reason ;)

That's not a problem, I figure since you can display information & filter from other models/tables searching seemed a natural extension of this facility.

comment:4 Changed 9 years ago by SmileyChris

It does seem like a natural extension. I've left it up to the developers to see whether they agree that it's worth it.

It'd probably help convince them if someone wrote the start of a patch... [hint hint] ;)

comment:5 Changed 9 years ago by Robert Myers <myer0052@…>

  • Resolution set to invalid
  • Status changed from new to closed

This works, no need for any code change, possibly documentation thought.

search_field = ['midas_number__company_name']

comment:6 follow-up: Changed 9 years ago by SmileyChris

#3346 created regarding lack of documentation of this feature.

comment:7 in reply to: ↑ 6 Changed 9 years ago by rfreitag@…

Replying to SmileyChris:

#3346 created regarding lack of documentation of this feature.

Legend...thanks so much for this I'm still quite new to Django and I was racking my brain....

comment:8 Changed 8 years ago by anonymous

Since the answer here wasn't immediately clear to me (I just started using Django today, so forgive me if I'm a bit dense!)

You can use the admin search fields to allow you to search on a related model by using a double underscore __ something like localFKfield__relatedfield would be the generic form I guess

Quick Example

class Partner(models.Model):
	name = models.CharField('Name of Partner Org',maxlength=255,unique=True)
	website = models.URLField('Website of Partner Org', blank=True)
	
	def __str__(self):
		return self.name
	
	class Admin:
		pass
	
	class Meta:
		verbose_name = "Partner Organization"
		verbose_name_plural = "Partner Organizations"
class Country(models.Model):
	name = models.CharField('Name of Country',maxlength=255)
	iso_code = models.IntegerField('ISO code')
	subregion = models.CharField('Sub-region',maxlength=255)
	subregion_iso = models.IntegerField('ISO code of Sub-region')
	parentregion = models.CharField('Parent-region',maxlength=255)
	parentregion_iso = models.IntegerField('ISO code of Parent-region')
	
	def __str__(self):
		return self.name
		
	class Admin:
		pass
	
	class Meta:
		verbose_name = "Country"
		verbose_name_plural = "Countries"

class Request(models.Model):
	request_id = models.CharField('Request ID ###N/AYY',primary_key=True,maxlength=6,unique=True)
	req_status = models.ForeignKey(ReqStatus, verbose_name = 'Current Status')
	partner_id = models.ForeignKey(Partner, verbose_name = 'Primary Partner')
	country_iso = models.ForeignKey(Country, verbose_name = 'Primary Destination Country')
	request_date = models.DateField('Date request received')
	request_boxes = models.IntegerField('Number of boxes requested')
	request_desc = models.TextField('Long description of request')
	contact_name = models.CharField('Name of Primary Contact at Partner Org.',maxlength=255)
	contact_email = models.EmailField("Contact's Email", blank=True)
	contact_phone = models.PhoneNumberField("Contact's Phone #",blank=True)
	fmsc_rep = models.CharField('Name of FMSC Representative',maxlength=255)
	reply_date = models.DateField('Date on which FMSC first replied')
	comments = models.TextField('Comments', blank=True)

	def __str__(self):
		return self.request_id+" - "+str(self.country_iso)+" via "+str(self.partner_id)+" ("+str(self.request_boxes)+" boxes)"
		
	class Admin:
		list_filter = ['req_status']
		search_fields = ['request_id','partner_id__name','country_iso__name']
		pass
	
	class Meta:
		verbose_name = "Request"
		verbose_name_plural = "Requests"

So the line search_fields = ['request_id', 'partner_id__name', 'country_iso__name'] means that you can now look up requests based on the request_id, the name of the partner OR the name of the country

Note: See TracTickets for help on using tickets.
Back to Top