Изменить поле формы модели на виджет ввода текста

Я хочу изменить виджет поля «trans_recipient» из раскрывающегося списка в поле ввода текста. В случае большого

Я пробовал следующее:

class SafeTransactionForm(forms.ModelForm):
''' SafeTranSactionForm '''
trans_recipient = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
class Meta:
    model = SafeTransaction
    fields = [ 'trans_recipient',
                'subject',
                'arbitrator_name',
                'payment_condition',
                'amount_to_pay']

Это производит это:

введите здесь описание изображения

и хотя сам виджет изменился, на самом деле попытка его использования приводит к ошибке значения как таковой: введите здесь описание изображения

без моей неправильной однострочной попытки изменить виджет:

class SafeTransactionForm(forms.ModelForm):
''' SafeTranSactionForm '''
class Meta:
    model = SafeTransaction
    fields = [ 'trans_recipient',
                'subject',
                'arbitrator_name',
                'payment_condition',
                'amount_to_pay']

раскрывающийся список:

введите здесь описание изображения

Я пробовал играть с синтаксисом, пытаясь обновить виджет в метаклассе, в основном я столкнулся с синтаксическими ошибками, и мне не удалось найти примеры этого конкретного случая после некоторых поисков в Google.

Понимание и объяснения очень приветствуются и ценятся.

РЕДАКТИРОВАТЬ:

Теперь я получаю сообщение об ошибке: ValueError: invalid literal for int() with base 10: 'inbox'

Трассировка стека: введите здесь описание изображения

Класс UpdateView:

class SafeTransUpdateView(UpdateView):
'''
    This view lets the user Update a SafeTransaction receipt
    then send an automatic email to the email address
'''
form_class = SafeTransactionForm
model = SafeTransaction
template_name = "myInbox/safeTrans_update.html"

def __init__(self, *args, **kwargs):
    self.request = kwargs.pop('request', None)
    super(SafeTransUpdateView, self).__init__(*args, **kwargs)

def form_valid(self, form):
    trans = form.save(commit=False)
    trans.save()
   ### Send an email to the user upon transaction update.
    usr_obj = User.objects.get(customuser=trans.trans_recipient)
    user_mail = usr_obj.email
    from_email = '[email protected]'
    contents = "This transaction [ " +trans.payment_condition+" ] has been updated !"
    email_subject = 'Transaction Update !'
    try:
        send_mail(email_subject, contents, from_email, [user_mail], fail_silently=False)
        pass
    except:
        pass
    else:
        pass
    return HttpResponseRedirect('inbox')

моя обновленная форма:

class SafeTransactionForm(forms.ModelForm):
''' SafeTranSactionForm '''
# trans_recipient = forms.CharField(widget=forms.TextInput(attrs={'class':'special'}))
trans_recipient = forms.ModelChoiceField(queryset=CustomUser.objects.all(),
widget=forms.TextInput(attrs={'value':"username"}), to_field_name="username")

def clean_trans_recipient(self):
    data = self.cleaned_data['trans_recipient']
    try:
        return CustomUser.objects.get(username=data)
    except CustomUser.DoesNotExist:
        raise forms.ValidationError("No user with this username exists")

class Meta:
    model = SafeTransaction
    fields = [  'trans_recipient',
                'trans_recipient_email',
                'subject',
                'arbitrator_name',
                'payment_condition',
                'amount_to_pay']

safeTrans_update.html :

        <h1>TRANSACTION UPDATE: </h1>
        <form action="{% url 'ST_update' object.pk %}" method="post">{% csrf_token %}
            {{ form.as_p }}
            <input type="submit" value="Confirm Update" />   
        </form>

URL.py:

 path('ST_update/<pk>',SafeTransUpdateView.as_view(),name='ST_update'),

Я хотел бы знать, почему сейчас возникает эта ошибка: ValueError: неверный литерал для int() с базой 10: 'inbox'. Любая информация очень ценится.


person timi95    schedule 30.08.2018    source источник
comment
Вы можете сделать это, но тогда вам нужно реализовать функцию clean_trans_recipient в форме, которая сопоставляет данные с действительным экземпляром CustomUser.   -  person Willem Van Onsem    schedule 30.08.2018
comment
См. здесь: docs.djangoproject. com/en/2.1/ref/forms/validation/   -  person Willem Van Onsem    schedule 30.08.2018


Ответы (1)


Проблема в том, что Django не знает, как преобразовать данные из поля формы обратно в атрибут trans_recipient для модели (который должен быть экземпляром CustomUser).

Однако это не проблема: вы можете выполнить очистку формы и, таким образом, написать пользовательскую функцию для преобразования строки обратно в объект CustomUser, например:

class SafeTransactionForm(forms.ModelForm):
    ''' SafeTranSactionForm '''
    trans_recipient = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))

    def clean_trans_recipient(self):
        data = self.cleaned_data['recipients']
        try:
            return CustomUser.objects.get(username=data)
        except CustomerUser.DoesNotExist:
            raise forms.ValidationError("No user with this username exists")

    class Meta:
        model = SafeTransaction
        fields = [ 'trans_recipient', 'subject', 'arbitrator_name',
                   'payment_condition', 'amount_to_pay' ]

Хотя вам, вероятно, потребуется сделать некоторые настройки для выборки CustomUser. Таким образом, мы стремимся получить такой CustomUser и вернуть его. Если такого CustomUser не существует, мы поднимаем ValidationError.

person Willem Van Onsem    schedule 30.08.2018
comment
Эй, именно эта вещь теперь выдает эту ошибку перед обновлением: invalid literal for int() with base 10: 'inbox' Я должен что-то приводить в Form или UpdateView, чтобы решить эту проблему. Любая помощь приветствуется. - person timi95; 19.01.2019
comment
Я совершенно уверен, что это не имеет ничего общего с этой формой. Я предлагаю вам задать новый вопрос с соответствующими моделями, формами, представлениями и т. д. и полной трассировкой. Просто сообщение об ошибке мало о чем говорит, так как эта ошибка может возникнуть откуда угодно. - person Willem Van Onsem; 19.01.2019
comment
Недавно я задал вопрос по этому поводу, но я полагаю, что он немного широк. Постараюсь сузить круг и посмотреть, ответит ли кто-нибудь. Я искал вокруг, эта ошибка кажется довольно общей, как вы говорите, я не слишком уверен, откуда она может быть, учитывая это. - person timi95; 19.01.2019
comment
@ timi95: обычно это ошибка, возникающая при фильтрации набора запросов или создании объекта, когда вы передаете строку для ForeignKey. Итак, что-то вроде Group.objects.filter(user='foo'), что не имеет смысла, поскольку user должно быть User, а 'foo' — это строка, а не пользователь. - person Willem Van Onsem; 19.01.2019
comment
Да, технически я делаю это, я полагаю, потому что я преобразовываю виджет раскрывающегося списка по умолчанию в виджет TextInput. Мой чистый метод выглядит так: CustomUser.objects.get(username=data) где данные: data = self.cleaned_data['trans_recipient'] Так же, как вы ответили мне в тот раз. - person timi95; 19.01.2019
comment
Но username здесь не CharField? - person Willem Van Onsem; 19.01.2019
comment
Я думаю, что это, вероятно, не так, и я, возможно, просматривал это. Есть ли способ бросить его как таковой, чтобы я мог проверить, не в этом ли проблема? - person timi95; 19.01.2019
comment
будет ли это работать : CustomUser.objects.get(username=str(data)) ? изменить: не сработало. - person timi95; 19.01.2019
comment
@ timi95: нет, что именно здесь username, это ключ. Если это ForeignKey, нам нужно запросить JOIN. - person Willem Van Onsem; 19.01.2019
comment
Я понимаю. CustomUser наследует это поле имени пользователя от User django.contrib.auth.models. Я посмотрел в определении, и это имя пользователя кажется строкой. - person timi95; 19.01.2019
comment
@ timi95: да, тогда я думаю, что ошибка не находится здесь. Но вы можете обновить вопрос с помощью полной трассировки, чтобы мы могли это проверить? - person Willem Van Onsem; 19.01.2019
comment
Хорошо, я сделаю это через несколько минут, наверное. Я постараюсь быть многословным об этом. - person timi95; 19.01.2019
comment
Привет, я изменил свой первоначальный вопрос. Не могли бы вы бросить беглый взгляд? - person timi95; 19.01.2019
comment
@ timi95: похоже, вы определили представление на основе классов для URL-адреса с атрибутом pk, но этот атрибут pk не является шаблоном int (здесь он inbox). Теперь некоторые представления (такие как UpdateView и т. д.) видят pk как специальную переменную URL: первичный ключ объекта для обновления, и поскольку pk в большинстве случаев является int, здесь это не складывается. Итак, я предполагаю, что что-то не так с этим шаблоном URL (или, по крайней мере, с тем, как вы с этим справляетесь). - person Willem Van Onsem; 19.01.2019
comment
Итак, это строка в url.py: path('ST_update/<pk>',SafeTransUpdateView.as_view(),name='ST_update'),, и это кнопка обновления, которая ведет меня к форме обновления: ` ‹a href={% url 'ST_update' pk=safeTrans_detail.id %}› ‹button style=margin -right:10px;› Обновить ‹/button› ‹/a› ` - person timi95; 19.01.2019
comment
Что ж, pk может иметь только int, поэтому вы можете ограничить путь, написав path('ST_update/<int:pk>', ...), а затем посмотреть, где именно создается недопустимый URL-адрес. Часть int: гарантирует, что отныне это представление будет срабатывать только с pk формы [0-9]+. - person Willem Van Onsem; 19.01.2019
comment
Я похоже решил свою проблему, просто добавив `\` к моему HttpResponseRedirect(' \inbox ') в методе form_valid(). Я по-прежнему включу <int:pk>, чтобы быть более точным. - person timi95; 19.01.2019