Как переопределить или скрыть значение поля формы модели администратора Django

В настоящее время у меня возникла проблема при переопределении значения поля формы на моей (Django==4.0.3) форме администратора django. Задача заключается в следующем: У меня есть определенная таблица пользователей, которую я подключаю к AWS Cognito. И когда администратор создает нового пользователя в django, система должна создать запрос на создание нового пользователя Cognito. Как только пользователь Cognito создан, он генерирует код "sub", а затем sub должен быть сохранен в django

Код следует

Модель

class BuyerUser(BaseModel):
buyer = models.ForeignKey(
    Buyer, on_delete=models.RESTRICT, related_name="%(class)s_buyer"
)
cognito_sub = models.CharField(max_length=50)
given_name = models.CharField(max_length=50)
family_name = models.CharField(max_length=50)
preferred_username = models.CharField(max_length=50)
email = models.EmailField(blank=False)
terms_conditions_accepted_datetime = models.DateTimeField(null=True, blank=True)

def __str__(self):
    return self.preferred_username

admin

class BuyerUsers(admin.ModelAdmin):
   list_display = ('id', 'buyer', 'given_name', 'family_name', 'preferred_username', 'available')
   list_filter = ('buyer', 'available',)
   list_display_links = ('id', 'preferred_username',)
   search_fields = ('buyer__name', 'preferred_username', 'available')
   list_per_page = 20

   form = BuyerUserChangeForm
   add_form = BuyerUserAddForm  # It is not a native django field. I created this field and use it in get_form method.

   def get_form(self, request, obj=None, **kwargs):
       """
       Use special form during foo creation
       """
       defaults = {}
       if obj is None:
           defaults['form'] = self.add_form
       defaults.update(kwargs)
       return super().get_form(request, obj, **defaults)
   admin.site.register(BuyerUser, BuyerUsers)

и мои формы

class BuyerUserAddForm(forms.ModelForm):
grupo = forms.CharField()

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
             initial=None, error_class=ErrorList, label_suffix=None,
             empty_permitted=False, instance=None, use_required_attribute=None,
             renderer=None):
    super().__init__(data, files, auto_id, prefix, initial, error_class, label_suffix, empty_permitted, instance,
                     use_required_attribute, renderer)
    self.cognito_sub = None

def save(self, commit=True):
    grupo = self.cleaned_data.get('grupo', None)
    self.given_name = self.cleaned_data.get('given_name', None)
    self.family_name = self.cleaned_data.get('family_name', None)
    self.preferred_username = self.cleaned_data.get('preferred_username', None)
    self.email = self.cleaned_data.get('email', None)
    cognito = CognitoDriver()
    sub = cognito.parse_user(
        cognito.create_user(self.preferred_username, self.email)["User"]
    )["Sub"]
    self.cognito_sub = sub
    cognito.add_group(self.preferred_username, grupo)


    return super(BuyerUserAddForm, self).save(commit=commit)

class Meta:
    model = BuyerUser
    # fields = '__all__'
    exclude = ['terms_conditions_accepted_datetime']


class BuyerUserChangeForm(forms.ModelForm):
    class Meta:
        model = BuyerUser
        fields = '__all__'

создать

django create admin

Change

django change admin

Это поле cognito sub должно иметь переопределенное значение после создания cognito-user. как это должно происходить в следующем коде

cognito = CognitoDriver()
sub = cognito.parse_user(
    cognito.create_user(self.preferred_username, self.email)["User"]
)["Sub"]
self.cognito_sub = sub

На самом деле, этот когнито-пользователь создается, и саб корректен. БОЛЬШАЯ ПРОБЛЕМА в том, что этот саб не сохраняется. Он получает только значение из формы. Я пытался скрыть поле sub с помощью exclude = ['cognito_sub','terms_conditions_accepted_datetime']. но получается только сохранить пустое значение.

Вы можете спросить, почему я использую Forms вместо того, чтобы просто переопределить метод model.Save() и ответ таков: мне нужно поле grupo, но это поле должно быть персистировано в DB. Оно существует только в Cognito.

Вы должны присвоить значение form.instance, а не непосредственно самой форме.

class BuyerUserAddForm(forms.ModelForm):
    grupo = forms.CharField()

    # ...

    def save(self, commit=True):
        grupo = self.cleaned_data.get('grupo', None)
        self.preferred_username = self.cleaned_data.get('preferred_username', None)
        self.email = self.cleaned_data.get('email', None)
        cognito = CognitoDriver()
        sub = cognito.parse_user(
        cognito.create_user(self.preferred_username, self.email)["User"])["Sub"]
        self.instance.cognito_sub = sub
        cognito.add_group(self.preferred_username, grupo)

        return super(BuyerUserAddForm, self).save(commit=commit)

Возможно, вы даже захотите полностью отключить поле ввода с помощью атрибута disabled. https://docs.djangoproject.com/en/4.0/ref/forms/fields/#disabled

class BuyerUserAddForm(forms.ModelForm):
    cognito_sub = forms.CharField(disabled=True)
    # ...
Вернуться на верх