Inline-подобное решение для Django Admin, где Admin содержит ForeignKey для другой модели - PullRequest
16 голосов
/ 21 июня 2011

У меня есть несколько Customer, которые заказывают Appointment с.Каждый Appointment имеет ровно одного клиента, хотя клиент может быть забронирован для нескольких встреч, происходящих в разное время.

class Customer(model.Model):
    def __unicode__(self):
        return u'%s' % (self.name,)
    name = models.CharField(max_length=30)
    # and about ten other fields I'd like to see from the admin view.

class Appointment(models.Model):
    datetime = models.DateTimeField()
    customer = models.ForeignKey("Customer")
    class Meta:
        ordering = ('datetime',)

Теперь, когда администратор переходит к просмотру расписания, просматривая встречи (заказанныевремя) в админке, иногда они хотят видеть информацию о клиенте, у которого есть определенная встреча.Прямо сейчас им нужно будет запомнить имя клиента, перейти от Встречи к странице администрирования Клиента, найти запомненного Клиента и только после этого сможет просмотреть его информацию.

В идеале было бы замечательно что-то вроде встроенного администратора.Тем не менее, я могу только создать CustomerInline на странице администрирования Appointment, если Customer имел ForeignKey("Appointment").(Django определенно дает мне ошибку, говоря, что Customer не имеет ForeignKey к Appointment).Кто-нибудь знает подобную функциональность, но когда Appointment имеет ForeignKey('Customer')?

Примечание: я упростил модели;фактическое поле Customer в настоящее время имеет около ~ 10 полей помимо имени (некоторый свободный текст), поэтому было бы нецелесообразно помещать всю информацию в __unicode__.

Ответы [ 3 ]

7 голосов
/ 21 июня 2011

Нет простого способа сделать это с Django.Строки предназначены для отслеживания отношений в обратном направлении.

Потенциально наилучшей заменой будет предоставление ссылки на объект пользователя.В представлении списка это довольно тривиально:

Добавьте метод к вашей модели встречи, например:

def customer_admin_link(self):
    return '<a href="%s">Customer</a>' % reverse('admin:app_label_customer_change %s') % self.id
customer_admin_link.allow_tags = True
customer_admin_link.short_description = 'Customer'

Затем в свой ModelAdmin добавьте:

list_display = (..., 'customer_admin_link', ...)

Другое решениеЧтобы получить именно то, что вам нужно, за счет того, что вы немного сложнее, нужно определить пользовательский шаблон администратора.Если вы делаете это, вы можете делать что угодно.Вот руководство, которое я использовал ранее для объяснения: http://www.unessa.net/en/hoyci/2006/12/custom-admin-templates/

В основном скопируйте форму изменений из исходного кода django и добавьте код для отображения информации о клиенте.

4 голосов
/ 21 июня 2011

Завершение @ John's ответа сверху - определите, что вы хотели бы видеть в своем списке изменений:

return '<a href="%s">%s</a>' % (
                     reverse('admin:applabel_customer_change', (self.customer.id,)),
                     self.customer.name # add more stuff here
             )

И чтобы добавить это в форму изменений, см .: Добавьте пользовательский html между двумя полями модели в форме изменения администратора Django

1 голос
/ 21 июня 2011

В классе ModelAdmin для ваших встреч вы должны объявить следующий метод:

class MySuperModelAdmin(admin.ModelAdmin):
  def get_form(self, request, obj=None, **kwargs):

    if obj:
      # create your own model admin instance here, because you will have the Customer's
      # id so you know which instance to fetch
      # something like the following
      inline_instance = MyModelAdminInline(self.model, self.admin_site)
      self.inline_instances = [inline_instance]

    return super(MySuperModelAdmin, self).get_form(request, obj, **kwargs)

Для получения дополнительной информации просмотрите источник этой функции, чтобы получить представление о том, к чему у вас будет доступ.

https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L423

...