问题
Here's part of my models.py:
class Person(models.Model):
birth_year = WideYear(null=True, blank=True)
birth_year_uncertain = models.BooleanField()
death_year = WideYear(null=True, blank=True)
death_year_uncertain = models.BooleanField()
flourit_year = WideYear(null=True, blank=True)
flourit_year_uncertain = models.BooleanField()
FLOURIT_CHOICES = (
(u'D', u'Birth and death dates'),
(u'F', u'Flourit date'),
)
use_flourit = models.CharField('Date(s) to use', max_length=2, choices=FLOURIT_CHOICES)
def __unicode__(self):
if self.personname_set.filter(default_name__exact=True):
name = z(self.personname_set.filter(default_name__exact=True)[0])
else:
name = u'[Unnamed person]'
if self.use_flourit == u'D':
dates = '%s - %s' % (z(self.birth_year), z(self.death_year))
else:
dates = 'fl. %s' % (z(self.flourit_year))
return '%s (%s)' % (name, dates)
class Meta:
ordering = ['ordering_string']
class PersonName(models.Model):
titles = models.CharField(max_length=65535, null=True, blank=True)
surname = models.CharField(max_length=255, null=True, blank=True)
first_name = models.CharField(max_length=255, null=True, blank=True)
middle_names = models.CharField(max_length=255, null=True, blank=True)
post_nominals = models.CharField(max_length=65535, null=True, blank=True)
default_name = models.BooleanField()
person = models.ForeignKey(Person, null=True, blank=True)
def __unicode__(self):
return '%s, %s %s' % (self.surname, self.first_name, self.middle_names)
class Meta:
unique_together = ("titles", "surname", "first_name", "middle_names", "post_nominals", "person")
unique_together = ("default_name", "person")
post_save.connect(post_save_person_and_person_name, sender=PersonName)
I want PersonName to be editable inline with Person in the admin as a TabularInline. Also, I want the default_name field of PersonName to display as a radio button, such that only one PersonName per Person can have default_name=True.
It's that last part that's the hard bit. Having a radio button interface within a form is relatively easy in Django. Having one that selects, essentially, one form in a formset, appears to be much, much harder.
One way to do this would be to add JavaScript to the change_form.html for Person that uses a regex to match the <input> elements for default_name and ensures that checking one of them unchecks the rest. But this seems as though it might become broken if Django's convention for naming HTML form fields changes; plus, it would only fix matters for users with JavaScript-enabled browsers.
Any better ideas gratefully received!
UPDATE 17/9/2009
The following admin template extension (based on this and this) implements the JavaScript suggestion above, but better solutions would be welcomed!
{% extends "admin/change_form.html" %}
{% block extrahead %}
<script src="/site_media/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
// Replace default_name checkboxes with radio buttons.
$(".default_name input").each(function(){
var name = $(this).attr('name'); // grab name of original
var id = $(this).attr('id'); // grab id of original
if ($(this).attr('checked')) { // grab checked value of original
var checked = ' checked="checked"';
} else {
var checked = '';
}
/* create new visible input */
var html = '<input type="radio" name="'+name+'" id="'+id+'" value="True"'+checked+' />';
$(this).after(html).remove(); // add new, then remove original input
});
// Ensure only one default_name radio button can be checked at a time.
$(".default_name input").click(function(){
$(".default_name input").not(this).removeAttr("checked");
});
});
</script>
{% endblock %}
回答1:
I think you won't be getting a conventional HTML-only method of doing what you want.
You shouldn't have to rely on regex here though. Can't you add a class name to your input fields so that jquery...
I guess that's harder than I first thought (answered here): Define css class in django Forms
It's only a slightly better solution though.
来源:https://stackoverflow.com/questions/1432745/select-item-in-django-admin-inline-with-radio-buttons