Form with related fields?

I have a model Account with a 1:1-relation to a Django User.

class Account(models.Model):
    user = OneToOneField(User, on_delete=models.CASCADE)
    description = CharField(max_length=255)

    def save(self, *args, **kwargs):
        secret = get_random_string(32)
        user = User.objects.create_user(
            username=uuid.uuid4(),
            password=make_password(secret, salt="<MYSALT>"),
        )
        self.secret_partial = secret[-3:]
        self.user = user
        super().save(*args, **kwargs)

and this ModelForm

class AccountForm(ModelForm):
    class Meta:
        model = Account
        fields = ["description"]

The idea is that someone can create an (API) Account that automatically creates a user with a password with a specific salt (so I can later to a lookup by API Secret, but that’s not important here).

I’d like user to pick a description, which is a field of Account, but also pick permissions from a limited set.

If I would try to describe what I want to do in code, it would be this:

class AccountForm(ModelForm):
    class Meta:
        model = Account
        fields = ["description", "user__user_permissions"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        api_permissions = ["can_manage_api_accounts"]
        self.fields["user_permissions"].queryset = Permission.objects.filter(
            codename__in=api_permissions
        )

This doesn’t work, of course. But how would I do such a thing?

You’re on the right track. But the references to permissions is a many-to-many reference and not a field on the model. As a result, you should be creating a non-model form field - perhaps named permissions, as a ModelMultipleChocieField. It’s the queryset and content for that field that you can filter.

You are calling a field (user__user_permissions) that does not exist in the model.

You must create an many to many field named user__user_permissions in the model, or create a separate form field.

The model form basically imports the fields of the inherited model.

If you want to write a field that is not included in the model, you must write it directly in the form.

This is an invalid suggestion. You cannot create a model field by this name. (It’s illegal to have consecutive underscores within a field name. See Field name restrictions)