dzerrenner / easy-select2-m2m Goto Github PK
View Code? Open in Web Editor NEWwork in progress for m2m feature in django-easy-select2
work in progress for m2m feature in django-easy-select2
This is continue of asyncee/django-easy-select2#4 discussion.
First of all, the models.py with improved Parent.__str__
method:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=127)
def __str__(self):
return self.name
class Parent(models.Model):
tags = models.ManyToManyField(to='Tag', null=True, blank=True, symmetrical=False)
def __str__(self):
return ",".join([unicode(t) for t in self.tags.all()])
Form validation starts with full_clean
method. First of all, it validates every field, then clean()
method is called. In your case, the ValidationError happened in _clean_fields method, so clean()
was never called.
Changes I made:
Set form initial value as a string, instead of list of ids, because Select2 tags expects a string.
Extended a full_clean
method that cleans tags
using raw form data:
from django.contrib import admin
from django import forms
from easy_select2 import Select2TextInput
from demoapp.models import Tag, Parent
class ParentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ParentForm, self).__init__(*args, **kwargs)
def get_choices():
values = Tag.objects.values_list('name', flat=True).distinct().order_by('name')
return [x for x in values]
# set select2attrs as stated in https://github.com/asyncee/django-easy-select2/issues/4
self.fields['tags'].widget = Select2TextInput(
select2attrs={
'tags': get_choices(),
},
)
self.initial = {
'tags': ', '.join([unicode(t) for t in self.instance.tags.all()]),
}
# remove the "Use Ctrl for multiple selections" help text
self.fields['tags'].help_text = ""
def full_clean(self):
#
# Tags input should be a list of ids (ints), but for now
# it is list of single unicode strings, so we should convert
# it to correct format.
#
# Althought this approach is working, it is better to create
# custom field type that will do appropriate conversions.
#
tags_names = self.data.get('tags')
if tags_names is not None:
tags_names = tags_names.split(',')
tags_ids = []
for name in tags_names:
try:
# It is possible to use get_or_create here.
t = Tag.objects.get(name=name)
except Tag.DoesNotExist:
pass
else:
tags_ids.append(unicode(t.id))
self.data['tags'] = tags_ids
super(ParentForm, self).full_clean()
class ParentAdmin(admin.ModelAdmin):
form = ParentForm
admin.site.register(Parent, ParentAdmin)
admin.site.register(Tag)
Hope it helps.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.