Let's say I have this model:
class Foo(models.Model):
bar = models.ForeignKey(Bar)
currency = models.ForeignKey(Currency) # currency is just an example
is_active = models.BooleanField()
Now suppose Foo is an Inline of Bar. And I would always want to indicate a value on each currency? If I could replace those currency drop down menus with a widget that just returns the name as text with a hidden field. So for example, on an add page, instead of having the inline show this:
- currency drop down menu is_active checkbox
- currency drop down menu is_active checkbox
- currency drop down menu is_active checkbox
have it show this:
- currency name 1 is_active checkbox
- currency name 2 is_active checkbox
- currency name 3开发者_StackOverflow is_active checkbox
- currency name 4 is_active checkbox
- currency name 5 is_active checkbox
What would be the right approach to accomplish that? I assume I would have to override some form class method. Thanks.
If you always want to use the same currency:
currency = models.ForeignKey(Currency, default = lambda: Currency.objects.get(...)
If you want to change the currency on the fly subclass the form and override init where you can do your magic on self.fields['currency']
.
If you would like to hide the field, use widget = forms.HiddenInput()
on that field in the form class.
I think that answers your question, but not your real problem. Use [django-currencies][1] for flexible handling of currencies.
[1]: http://code.google.com/p/django-currencies/ django-currencies
The first problem to solve here is pre-generation of the appropriate linked Foos for each Bar. You could do that in a custom save() method on Bar, or using signals, or in a Bar factory method on a BarManager...
Once that's done, I think your admin problem can be solved like this:
class FooInline(admin.TabularInline):
formfield_overrides = {models.ModelChoiceField: {'widget': ReadOnlyWidget}}
model = Foo
extra = 0
Where you'd use a custom ReadOnlyWidget like the one here.
I solved it with javascript. Insert the below into the top of tabular or stacked template. It assumes the name column is named name.
{% with inline_admin_formset.opts as i %}
{% if i.pre_filled %}
<script language="JavaScript" type="text/javascript">
jQuery(function($) {
var pre_values = [
{% for name in i.pre_filled %}
{% if forloop.last %}
[{{ name.id }}, "{{ name.name }}"]
{% else %}
[{{ name.id }}, "{{ name.name }}"],
{% endif %}
{% endfor %}
];
$.each( pre_values,
function( i, value ){
$('div.inline-group div.tabular').each(function() {
$("#id_{{ i.verbose_name|lower|cut:" " }}_set-" + i + "-{{ i.pre_field }}").after(value[1]);
$("#id_{{ i.verbose_name|lower|cut:" " }}_set-" + i + "-{{ i.pre_field }}").val(value[0]).hide();
$("#lookup_id_{{ i.verbose_name|lower|cut:" " }}_set-" + i + "-{{ i.pre_field }}").hide();
$("strong").hide();
});
}
);
});
</script>
{% endif %}
{% endwith %}
And this goes in your inline.py:
class MyCustomInline(admin.TabularInline):
pre_filled = []
pre_field = ''
def get_fieldsets(self, request, obj=None):
if not obj and self.pre_filled and self.pre_field:
count = self.pre_filled.count()
self.extra = count
self.max_num = count
if self.raw_id_fields:
self.raw_id_fields.append(self.pre_field)
else:
self.raw_id_fields = [self.pre_field]
return super(MyCustomInline, self).get_fieldsets(request, obj)
class FooInline(MyCustomInline):
model = Foo
pre_filled = Currency.objects.all()
pre_field = 'currency'
精彩评论