Hi Django users, I want a ManyToManyField(A) to be shown in a textarea as a formatted list of a model field _x_ in the corresponding related model A (not a list of the A's pk field, which is easier). If a value for _x_ that does not exist in A is added, then I want a new record added to A (by implication, field _x_ is unique).
I have recently implemented this as follows, and it works but I (I think) but I want to know if I went about it the right way. Any comments would be appreciated. (Also, it's a useful bit of code, so you should check it out.) As an example, consider the following models for University courses: class Student(models.Model): email = models.EmailField(unique=True) ... class Course(models.Model): name = models.CharField(max_length = 100) students = models.ManyToManyField(Student) ... I want the administrator to be able to enter a comma separated list of emails into a textarea. If the email does not exist in Student, a new Student should be added. To solve this, I have class CourseAdmin(admin.ModelAdmin): form = CourseForm ... class CourseForm(ModelForm): students = MultiEmailField() def __init__(self, *args, **kwargs): super(CourseForm, self).__init__(*args, **kwargs) if self.initial.has_key('students'): self.initial['students'] = ",".join( [course_student.email for course_student in CourseStudent.objects.filter(pk__in = self.initial['students'])]) def save(self, *args, **kwargs): emails = self.cleaned_data['students'] for email in emails: # create a new Student if one does not already exist form = StudentForm({'email': email}) if form.is_valid(): form.save() self.cleaned_data['students'] = Student.objects.filter (email__in=emails) return super(CourseForm, self).save(*args, **kwargs) class Meta: model = Course class StudentForm(ModelForm): class Meta: model = Student MultiEmailField is essentially the same as specified in http://docs.djangoproject.com/en/dev/ref/forms/validation/#form-field-default-cleaning. Assume is_valid_email is defined, and don't worry about the details of MultiEmailField (the actual implementation lets you use spaces, semicolons, commas and newlines as delimiters): class MultiEmailField(forms.Field): def clean(self, value): """ Check that the field contains one or more comma-separated emails and normalizes the data to a list of the email strings. """ if not value: raise forms.ValidationError('Enter at least one e-mail address.') emails = value.split(',') for email in emails: if not is_valid_email(email): raise forms.ValidationError('%s is not a valid e-mail address.' % email) # Always return the cleaned data. return emails Please comment on my code in CourseForm: * Does the logic belong here instead of in the model? * Are there bugs that you can see? * Is this the right way to do things? * Is it elegant? (I think the answer is no.) Any comments are appreciated. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---