Populating values in django-admin based on a forei

2020-07-17 16:01发布

问题:

I have a model with a foreign key reference that looks something like this

class Plan(models.Model):
    template = models.ForeignKey(PlanTemplate)
    throttle = models.IntegerField(default=10)
    rate_limit = models.BigIntegerField(default=60)

and the foreign key model:

class PlanTemplate(models.Model):
    name = models.CharField(max_length=50)
    throttle = models.IntegerField(default=10)
    rate_limit = models.BigIntegerField(default=60)

I'd like to have the throttle and rate_limit on the Plan admin page be auto-populated when a PlanTemplate is selected. Is this something django-admin can easily be made to do, or do I have to override the admin template and add some custom javascript?

I am running Django 1.2.4.

回答1:

I found a way to do this, but it had to involve javascript, which was actually pretty straight forward. I created a change_form.html in the templates/admin/billing/ directory which looked like this.

{% extends "admin/change_form.html" %}

{% block extrahead %}
    <script src="{{MEDIA_URL}}js/jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
      $(document).ready(function() {
        $('#id_template').change(function() {
          $.ajax({
            type: 'POST',
            url: "{% url get_template_info %}",
            data: {'template_id': $('#id_template').val()},
            success: function(data, _status) {
              $('#id_throttle').val(data.throttle);
              $('#id_rate_limit').val(data.rate_limit);
              $('#id_product').val(data.product);
              $('#id_tier_group').val(data.tier_group);
            },
            dataType: "json"
          });               
        });
      });
    </script>
{% endblock %}

which hits a view that simply takes the id passed in, queries it up and returns it to the call. Works like a charm.



回答2:

This would be easy to do if you made it a 2 step process. Perhaps, having an add_view that only has 1 field, template.

Otherwise, you'll have to use JavaScript and set up a view that returns template data.

Here's an easy solution using model admin and a 2 step form:

class MyAdmin(ModelAdmin):
    # ...

    def add_view(self, request, form_url='', extra_context=None):
        self.fields = ['template'] # add view has only 1 field.
        return super(MyAdmin, self).add_view(request, form_url, extra_context)

    def save_model(self, request, obj, form, change):
        if not change:
            # if adding... populate defaults.
            obj.throttle = obj.template.throttle
            obj.rate_limit = obj.template.rate_limit
            obj.save()