Django Model Choice Option as a Multi Select Box

django model choice option as a multi select box

Can a Car have multiple colors? In that case color ought to be a many to many relationship rather than a CharField. If on the other hand you want to do something like Unix permissions (i.e. Red + Blue, Red + Blue + Green etc.) then assign numeric values of to each of them and make color an integer field.

Update

(After reading comment) You can use a custom form to edit your model in Admin instead of the default ModelForm. This custom form can use a multiple choice widget that lets users select multiple colors. You can then override the clean() method of the form to return a suitably concatenated value ('RB' etc.).

Update 2

Here is some code:

First, remove the choices from the model field. Also increase its maximum size to 2. We don't want choices here - if we do, then we'll have to add a choice for each combination of colors.

class Car(models.Model):
...
color= models.CharField(max_length=2)

Second add a custom ModelForm to use in admin app. This form will override color and instead declare it as a multiple choice field. We do need choices here.

COLORS= (
('R', 'Red'),
('B', 'Yellow'),
('G', 'White'),
)

class CarAdminForm(ModelForm):
color = forms.MultipleChoiceField(choices = COLORS)

class Meta:
model = Car

def clean_color(self):
color = self.cleaned_data['color']
if not color:
raise forms.ValidationError("...")

if len(color) > 2:
raise forms.ValidationError("...")

color = ''.join(color)
return color

Note that I have added only a couple of validations. You may want more and/or customize the validations.

Finally, register this form with admin. Inside your admin.py:

class CarAdmin(admin.ModelAdmin):
form = CarAdminForm

admin.site.register(Car, CarAdmin)

Django multiple choice and multi-select field in model and form

You need to create a many-to-many relationship to a new model, let's call it Skill, that represents the available skills that can be dynamically created.

class Profile(models.Model):
# ...

skills = models.ManyToManyField(
to='myapp.Skill', # use a string in the format `app_name.model_name` to reference models to avoid issues using the model before it was defined
related_name='user_profiles', # the name for that relation from the point of view of a skill
)

class Skill(models.Model):
name = models.CharField(max_length=255)
abbreviation = models.CharField(max_length=3)

Then in your form you can just add that many-to-many field skills. It will by default be a multiple choice field in the django admin.

The relation can have zero to n entries for each pair of profile and skill. In other words, every user can have zero to n skills and vice versa.

To allow for a default value you will have to write a custom migration that creates that default entity of a Skill to make sure it is in the database at runtime.

in django admin, can we have a multiple select based on choices

ChoiceField is not really suitable for multiple choices, instead I would use a ManyToManyField. Ignore the fact that Choices can be used instead of ForeignKey for static data for now. If it turns out to be a performance issue, there are ways to represent this differently (one being a binary mask approach), but they require way more work.

Django Form | Group Model | MultiSelect | getting only single value from the form by using MultiSelect widget

If you access request.POST.get('key') (or request.POST['key']), you only get the last value associated with that key.

You access all values with the .getlist(…) method [Django-doc]:

print(request.POST.getlist('the_choices'))

But normally you process data with the form itself, so:

form = MyForm(request.POST, request.FILES)
if form.is_valid():
print(form.cleaned_data['the_choices'])

This will also clean the data and return model objects, not their primary keys.

Multiple-select form and query django

You can use .getlist(…) [Django-doc] to obtain the list of options, and then use the __in lookup [Django-doc] to retrieve the vehicles where the status is one of the elements in the list:

choices = request.GET.getlist('choice')

vehicles = vehicles.filter(status__in=choices).order_by('-date_posted')

Django - Saving multiple selection boxes in one form

Yes you are right

POST data is not coming as dictionary.

You are looping on years and rendering select and input tag inside form and the name attribute of all select and input tags are same that is rating and year simultaneously

in that case when you submit your form you will get a list of rating and year so you should use getlist() method while fetching it from request.POST QueryDict.

request.POST.getlist('rating[]')
request.POST.getlist('year[]')

if above doesn't work use it like

request.POST.getlist('rating', [])
request.POST.getlist('year', [])

Update your rates method like.

class ChoiceManager(models.Manager):
def rates (self, Assignment_id, rating, year):
...
# you can use year also to find the length
for i in range(len(rating)):
rated = Choice.create(
assignment = assignment,
year = year[i],
rating = rating[i]
)

change method call.

rates = Choice.objects.rates(Assignment_id,request.POST.getlist('rating[]'), request.POST.getlist('year[]'))

Multiple select Django keeps throwing not a valid value

The solution turns out to be very simple, django-crispy-forms.

Once I've added the required settings in settings.py

I updated my create-blog.html:

{% load crispy_forms_filters %}

<form class="create-form" method="post" enctype="multipart/form-data">
{% csrf_token %}

{{ form | crispy }}

{% for field in form %}
<p>{% for error in field.errors %}
<p style="color: red;">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}

{% if form.non_field_errors %}
<div style="color:red;">
<p>{{ form.non_field_errors }}</p>
</div>
{% endif %}

<!-- Submit btn -->
<button class="submit-button btn btn-lg btn-primary btn-block" type="submit">POST</button>
</form>

Make sure to load crispy_forms_filters at the top of the file.

In my views.py I have to use save_m2m since I've used obj.save(commit=False).

def create_blog_view(request):
context = {}

user = request.user
categories = Category.objects.all
statuses = BlogPost.STATUS

if not user.is_authenticated:
return redirect('login')

form = CreateBlogPostForm(request.POST or None, request.FILES or None)

if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(username=user.username).first()
obj.author = author
obj.save()
form.save_m2m()
form = CreateBlogPostForm()

context['form'] = form
context['categories'] = categories
context['statuses'] = statuses

return render(request, 'my_simple_blog/create-blog.html', context)

And you should be able to do multiple select and the choices will be reflected in Django Admin.

Django - dropdown form with multiple select

"Dropdown" boxes don't support multiple selection in HTML; browsers will always render it as a flat box as your image shows.

You probably want to use some kind of JS widget - Select2 is a popular one. There are a couple of Django projects - django-select2, django-easy-select - that aim to make it simple to integrate that into your form; I have no experience with either of them.

(And yes, that snippet - like many things on Djangosnippets - is massively out of date; "newforms" was renamed to "forms" even before version 1.0 of Django.)



Related Topics



Leave a reply



Submit