Django - Field attributes in widget context - django

As I am using some more exotic css framework I would like to change the behaviour of the text input (provide it with label etc. by default).
I have overridden the template in django/forms/widgets/input.html
Unfortunately the widget context is missing the field, so I cannot use field properties like help_text, label, etc in my template. Therefore I would need to override the TextInput widget.
My two options are now:
Setting my own widget class for every single field in my Form / Modelform classes
Using My custom ModelForm which iterates all the fields in __init__ and replaces the widget.
Is there any better way to override django's default text_input widget?
Does is there any other way to get field.errors and field.label into the widget
(Or is there a reason why there is no label in the widget context)?

Related

How to display a custom form with multiple widgets for a field in Django admin?

The Django docs say you can add a form to the admin UI:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
I want a custom editing UI for a special field in my model, where I display multiple widgets. (It's not exactly the same, but an analogy might be an old-school hex editor widget, where you want fine editing control on a big blob of information.) Perhaps I could break the multiple values into multiple database objects and use an InlineAdmin, but I have app-specific reasons to not do that.
I thought I'd use a Form object with some custom fields, but Django says it must be a ModelForm:
<class 'myapp.admin.MyAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'.
Is it possible to display multiple widgets (basically a very custom form) for a single model value in Django admin?
EDIT: It looks like MultiWidget might work? I'm gonna look into that. Also, this question is related. That suggests I should just change the widget on the field.
The answer was to make a MultiWidget, overriding:
__init__ to set up the widgets
decompress and value_from_datadict to unpack and pack the field value
template_name to render my own template
get_context to make the context for the template

DjangoAdmin: How to keep the '+✎ ✕' buttons for a Foreign Key on when using `AutocompleteSelect` widget

I'm using the AutocompleteSelect widget for a ForeignKey field. To do this, I override the default Admin Form using the ModelForm class like this:
class ContainerModelForm(forms.ModelForm):
...
some_fk = forms.ModelChoiceField(
queryset=SomeModel.objects.all(),
widget=AutocompleteSelect(ContainerModel.some_fk.field.remote_field, admin.site)
)
However, by using this widget I lose the + ✎ ✕ buttons that are available on the Django Admin interface for a Foreign Key field by default.
What will be a good way to use AutoCompleteSelect widget but also keeping these Add/Edit/Delete buttons besides the foreign key field on the Admin UI?
Django seems to wrap widgets for ForeignKey and ManyToManyField from model regardless of the form field type / widget used.
https://github.com/django/django/blob/920448539631b52dcee53bd32a880abbc9de18bd/django/contrib/admin/options.py#L144-L175
Are you sure some_fk is an actual field in the model?
Even if it's not, you can probably achieve something similar by wrapping it the same way.

In Django Forms, how to add a filter to a SelectedMultiple control?

I'm working with Django Forms. In my model, i have a ManyToMany relationship between class X and class Y and Django shows a very annoying MultipleChoice control to edit this relationship. I would like to add a filter so editing the X object the user can filter the Y objects by name while he writes the name to finally select them
Some idea about how to do this in Django?
By default, a ManyToManyField in a Django Model will be represented by a ModelMultipleChoiceField in the ModelForm, which itself uses a SelectMultiple widget. This widget uses the default browser <select multiple="multiple"> element, which results in your "annoying" multiple choice control.
So in order to replace it, you should override the ModelMultipleChoiceField in your form to pass it your own widget (which would subclass SelectMultiple and override the template used):
my_field = forms.ModelMultipleChoiceField(queryset=Y.objects.all(), widget=MySelectMultiple)
However, many people have already done this kind of thing, so it's probably easier to use a package that has a nice multiple choice widget to your liking.
A very popular jquery module on the front-end is select2. If you want to use it, there are some django packages that already support it, popular ones are django-autocomplete-light and django-select2

Customize radioselect default renderer

I have the following form with radioselect options :
jobStatus = forms.ChoiceField( widget=forms.RadioSelect())
However, it renders the radio buttons in <ul> <li> .. </li></ul> tags.
Could you suggest me any way to render the only radiobutton input ?
Thanks
This is a nice how-to for overriding the renderer of the radio select widget.
https://wikis.utexas.edu/display/~bm6432/Django-Modifying+RadioSelect+Widget+to+have+horizontal+buttons
Basically, create a class that inherits from the forms.RadioFieldRenderer class and override the render method. Then in your form when setting the widget use the renderer argument to set the renderer to your custom renderer class.
That being said, I usually just change the appearance using CSS

Django forms question

I want to generate a form from a model. However one of the fields in the model is a CharField, whose value is mostly "Option1" "Option2" or "Option3". If the user chooses "Other" I would like him to be able to type the value of the field.
How can I do this without having to write a whole form by hand?
I think one only way could be to build your own widget and associate that widget with that CharField on a ModelForm
Django Widgets
UPDATE
Here's a sample custom widget implementation that inherits from TextInput:
http://www.kryogenix.org/days/2008/03/28/overriding-a-single-field-in-the-django-admin-using-newforms-admin