[PYTHON] How to filter foreign keys that can be selected on the Django admin screen

This article is the third day of Django Advent Calendar 2019. (Advent calendar) is the first post.

Introduction

I'm a non-engineer who has been making apps personally with Django for the past month or so. When I used a foreign key in that app, when I opened the pull-down, more than 100 items were displayed, so I wondered if I could squeeze it somehow.

To conclude first, you can use limit_choices_to to filter the records displayed by foreign keys. Let's actually create an app and try it out to see how to use it.

The app I made for this article

I made a simple app for explanation. Only Model. By the way, the theme is an application that registers the prediction of which team the players who acquired the FA right in 2019 will go to. It's almost decided, so it's not practical! https://github.com/shimayu22/fa_expects_app/

In the FaExpects table, the Players table is set as a foreign key so that registered players can select it from the pull-down menu. Player data is also available, so you can try it just by reading it. Please refer to README for how to use it.

things like this

https://github.com/shimayu22/fa_expects_app/tree/part1

スクリーンショット 2019-11-23 23.01.18.png

Is it possible to filter on the management screen?

Use limit_choices_to

From ForeignKey.limit_choices_to in the Django documentation

Set limits on the choices available in this field when this field is rendered using ModelForm or admin (by default, all objects in the query set can be selected). You can use either a dictionary, a Q object, or a callable object that returns a dictionary or Q object. (Google Translate)

So you can use limit_choices_to to filter the selectable items.

I actually tried it

https://github.com/shimayu22/fa_expects_app/tree/part2

Added limit_choices_to to player_id of FaExpects.

models.py


    player_id = models.ForeignKey(
        Players,
        on_delete=models.CASCADE,
        verbose_name="player",
        limit_choices_to={"position":1,}
    )

This time, only the position of "1" (pitcher) can be selected. with this, http://127.0.0.1:8000/admin/fa_expects/faexpects/add/ When you open the "Player" pull-down menu,

スクリーンショット 2019-11-24 22.52.48.png

Only the players registered as pitchers were displayed!

Use search keywords

In the above example, you can narrow down by equality such as position == 1, but by using the search keyword, you can narrow down by using the above and the following.

models.py


    player_id = models.ForeignKey(
        Players,
        on_delete=models.CASCADE,
        verbose_name="player",
        limit_choices_to={"position": 1,
                          "age__lt": 33}
    )

The above stipulates position == 1 and age <33 (pitcher and under 33 years old). If you add __lt (two underscores) to the item name ʻage`, the condition" less than "is added.

スクリーンショット 2019-11-24 23.01.15.png

There are fewer players to choose from! The following articles are very well organized for other keywords.

Reference: [Summary of Django database operations #List of search keywords](https://qiita.com/okoppe8/items/66a8747cf179a538355b#%E6%A4%9C%E7%B4%A2%E3%82%AD%E3 % 83% BC% E3% 83% AF% E3% 83% BC% E3% 83% 89% E3% 81% AE% E4% B8% 80% E8% A6% A7)

Use Q object

Until now, search conditions were specified in dictionary type, but it is also possible to specify in Q object.

models.py


from django.db.models import Q

~~~abridgement~~~
    player_id = models.ForeignKey(
        Players,
        on_delete=models.CASCADE,
        verbose_name="player",
        limit_choices_to=Q(position=4) | Q(position=7),
    )

For Q objects, you can specify OR conditions like this. In the above, it means "the position is second baseman or outfielder".

スクリーンショット 2019-11-24 23.37.01.png

Only the second baseman or the outfielder could be displayed brilliantly!

Create a dictionary for limit_choices_to

https://github.com/shimayu22/fa_expects_app/tree/part3

If it is solid writing, it is not flexible, so I will create a dictionary type with a function and pass it. This time, in order to make it crisp, I made a table for specifying conditions. I am adding the RequestedConditions class to Models.py. (Because it is long, please check Models.py)

Then I created a function to create a dictionary for limit_choices_to from the latest record in the RequestedConditions table.

Models.py


~~~abridgement~~~

def set_players_condition():
    condition =  RequestedConditions.objects.latest('pk')
    condition_dict = {}
    if condition.age > 0:
        condition_dict["age__lt"] = condition.age
    
    if condition.position > 0:
        condition_dict["position"] = condition.position
    
    if condition.dominant_hand > 0:
        condition_dict["dominant_hand"] = condition.dominant_hand

    return condition_dict

~~~abridgement~~~

First, http://127.0.0.1:8000/admin/fa_expects/requestedconditions/add/ Set "age", "position", and "dominant hand" and save. (If you do not set all, all will be displayed)

スクリーンショット 2019-11-26 23.31.31.png

After registration http://127.0.0.1:8000/admin/fa_expects/faexpects/add/ If you look at the players in, only the players who meet the conditions will be displayed.

スクリーンショット 2019-11-26 23.31.57.png

I did it.

in conclusion

If you just want to do something with the model, you can do it like this. It seems that you can make it more flexible by combining Q objects. Please play around with it and try it out.

bonus

It may be natural if you think calmly, limit_choices_to={"age__lt":RequestedConditions.objects.latest('pk').age} If you write something like this, you will get an error saying "There is no such table" when you first migrate. Sora (when I try to reference a table that hasn't been created yet) Yes (I get an error) (Isn't it natural?).

Less relevant supplement

  1. Not the players who declared FA, but the players who got the FA right (I'm sorry if there is a mistake)
  2. Daichi Suzuki (B) is too much protected, so I decided to protect it most in 2019 (1).
  3. I'm a yak ham
  4. I'm looking forward to next season!

reference

Summary of Django database operations

Also, the following articles were helpful for Django in general. Thank you! [Python] Django Tutorial-Creating a General Purpose Business Web App Fastest [Django] Model Field Settings Template

Recommended Posts

How to filter foreign keys that can be selected on the Django admin screen
How to make only one data register on the Django admin screen
How to set variables that can be used throughout the Django app-useful for templates, etc.-
The story of failing to update "calendar.day_abbr" on the admin screen of django
How to add pre-save processing when adding objects on the Django admin site
[Django] About users that can be used on template
How to solve the problem that video content cannot be played on Firefox for Linux
Python standard module that can be used on the command line
Can the Kalman filter be used to predict stock price trends?
Hide the warning that zsh can be used by default on Mac
How to make a rock-paper-scissors bot that can be easily moved (commentary)
Linux screen distribution on Ubuntu Memo that wants to be a Linux screen distribution YouTuber
TLE seemed to be scary depending on how the input was received
How to check the version of Django
How to solve the problem that only the process remains when you press cross on the imshow screen of OpenCV
How to install a Python library that can be used by pharmaceutical companies
[Ubuntu 18.04 LTS] What to do when the screen resolution cannot be selected [NVIDIA]
How to print debug messages to the Django console
Implement the autocomplete feature on Django's admin screen
Customize the model page on Django's admin screen
Notes on how to use StatsModels that can use linear regression and GLM in python
How to create a property of relations that can be prefetch_related by specific conditions
How to solve the problem that the login screen is not displayed forever on Ubuntu 19.04 because it stops at the logo at startup
Simple statistics that can be used to analyze the effect of measures on EC sites and codes that can be used in jupyter notebook
Think about how to program Python on the iPad
How to put Takoyaki Oishikunaru on the segment tree
How to deploy a Django application on Alibaba Cloud
How to solve the recursive function that solved abc115-D
How to build a Django (python) environment on docker
How to use Django on Google App Engine / Python
Transit to the update screen with the Django a tag
How to enjoy Python on Android !! Programming on the go !!
How to run Django on IIS on a Windows server
Qiita can now be viewed on the console (shell)
Deep learning course that can be crushed on site
[Django] How to redirect unlogged-in users to the login page
List the classes that can be referenced by ObjCClass
How to deal with the phenomenon that Python (Jupyter notebook) executed on WSL becomes Aborted
How to deal with the problem that pandas 1.1.0 or later build fails on Alpine Linux
How to set up a simple SMTP server that can be tested locally in Python
[Django] Field names, user registration, and login methods that can be used in the User model
How to display hover text and text that can be executed by clicking with Minecraft plugin
How to deal with the error that Docker's MySQL container fails to start on Docker Toolbox
How to delete "(base)" that appears in the terminal when Anaconda is installed on Mac
[Python] A program to find the number of apples and oranges that can be harvested