Как обновлять models choice, если это поле ссылается на обьекты другой модели?

В Django существует несколько способов обновления полей choices в моделях.

Первый способ - явное определение полей choices внутри модели. Например, у нас есть модель User и модель City, и поле city модели User ссылается на обьекты модели City. Чтобы обновить choices для city, мы можем определить его явно:

class User(models.Model):
    CITY_CHOICES = [
        ('NYC', 'New York City'),
        ('LA', 'Los Angeles'),
        ('CHI', 'Chicago'),
    ]
    
    city = models.CharField(max_length=3, choices=CITY_CHOICES)

После определения новых значений choices в модели City, мы можем обновить модель User следующим образом:

from django.db.models.signals import post_migrate
from django.dispatch import receiver

@receiver(post_migrate)
def update_choices(sender, **kwargs):
    if sender.name == 'myappname':
        city_choices = [(city.code, city.name) for city in City.objects.all()]
        User._meta.get_field('city').choices = city_choices

Это сработает при каждом выполнении миграции приложения myappname, и обновит choices для поля city модели User в соответствии с новыми значениями из модели City.

Второй способ - использование метода get_choices внутри метода __init__ класса формы. Другими словами, мы можем создать форму, которая будет автоматически обновлять choices для поля city. Вот пример:

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('city',)
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['city'].choices = [(city.code, city.name) for city in City.objects.all()]

При создании экземпляра формы UserForm каждый раз, когда он будет отображаться, он будет обновлять choices для поля city на основе текущих значений из модели City.