Django ModelForm Validate custom Autocomplete for M2M, instead of ugly Multi-Select

痴心易碎 提交于 2020-01-02 07:04:29

问题


Given the following models (cut down for understanding):

class Venue(models.Model):
    name = models.CharField(unique=True)

class Band(models.Model):
    name = models.CharField(unique=True)

class Event(models.Model):    
    name = models.CharField(max_length=50, unique=True)       
    bands = models.ManyToManyField(Band) 
    venue = models.ForeignKey(Venue)
    start = models.DateField()
    end = models.DateField()

The admin area works great for what I'm doing, but I'd like to open the site up a bit so that certain users can add new Events. For the public portions, I have several "administrative" fields on these models that I don't want the public to see (which is easy enough to fix).

My specific problem, though, is changing the display of the ManyToMany selections when creating a new Event. Because the number of Bands possible to list for an event should not be sent along as a multiselect box, I'd like to use an AutoComplete that handles multiples (like the Tags box, here on StackOverflow!).

I have this part working, and it correctly fills in a hidden input with the Band.id's separated by commas for a value. However, I can't understand how to put together letting Django do the validation using the ModelForms, and somehow also validating the 'Bands' selection.

Ideally, I want to auto-complete like the tags here on StackOverflow, and send along the selected Bands ID's in some kind of Delimited string - all while letting Django validate that the bands passed exist, etc, as if I left the annoying multi-select list in place.

Do I have to create my own Auto-Complete Field type for a form or model, and use that? Is there something else I'm overlooking?

I have seen some existing AutoComplete widgets, but I'd really-really-really like to use my own Autocomplete code, since it's already set up, and some of them look a bit convoluted.

There was a lot more text/explanation here, but I cut back because I'm avoiding Wall Of Text. If I left important stuff out, let me know.


回答1:


It's a little hard to say without knowing exactly what your autocomplete code is doing, but as long as it is sending the ids of the bands like they would be sent with the <select>, the ModelForm should validate them as usual.

Basically, your POST string should look like:

name=FooBar2009&bands=1&bands=3&bands=4&venue=7&start=...

The easiest way to do this might be to use Javascript to add (and remove) a hidden input field for each band entered with the name band and the id of the band as the value. Then, when the user submits the form, the browser will take care of posting the right stuff, and the ModelForm will validate it.




回答2:


Using the annointed jquery autocomplete plugin,

On the client-side I have something like this:

jQuery("#id_tags").autocomplete('/tagging_utils/autocomplete/tasks/task/', {
    max: 10,
    highlight: false,
    multiple: true,
    multipleSeparator: " ",
    scroll: true,
    scrollHeight: 300,
    matchContains: true,
    autoFill: true,
}); 

So, I have a view that returns when I type in a:

http://skyl.org/tagging_utils/autocomplete/tasks/task/?q=a&limit=10&timestamp=1259652876009

You can see the view that serves that here:

http://github.com/skyl/skyl.org/blob/master/apps/tagging_utils/views.py

Now, it's going to be a little tricky .. you might except the POST, then in the clean method of the field try to .get() based on the strings and raise a form validation error if you can't get it ... right, name = ... unique=True .. so something like (off the top of my head) ... :

def clean_bands(self):
    return Band.objects.filter( name__in = self.cleaned_data['bands'].split(' ') )

You could also check each string and raise a form error if there are no bands by that name .. not sure that the clean method should return a qs. Let me know if this helps and you want me to keep going/clarify.



来源:https://stackoverflow.com/questions/1528059/django-modelform-validate-custom-autocomplete-for-m2m-instead-of-ugly-multi-sel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!