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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---