Django: несколько баз данных, маршрутизаторов и тестовой среды

#django #django-tests

#django #django-тесты

Вопрос:

В настоящее время я пишу тесты для нашего приложения django. К сожалению, нам пришлось использовать макет с несколькими базами данных, и мы не можем это изменить. (Распределенные базы данных с несколькими бэкэндами на разных серверах в нескольких центрах обработки данных)

У нас есть две базы данных:

  1. базы данных по умолчанию с таблицами django по умолчанию
  2. базы данных приложений с некоторыми моделями

Для этих моделей мы написали разные маршрутизаторы, как описано на сайте django. Теперь проблема, если я запускаю python manage.py test customerreceipts тестовая платформа умирает через несколько секунд со следующей ошибкой:

 django.db.utils.ProgrammingError: relation "auth_user" does not exist
  

Я проверил созданную базу данных, и там не было таблиц. Из-за этого запрос из модели выдает ошибку.

Модель проблемы (в базе данных 2):

 class CustomerReceipts(models.Model):

    def _choices_user():
        users = User.objects.all()
        users = users.order_by('id')
        return [(e.id, e.username) for e in users]

    # General
    receipt_name = models.CharField(max_length=20, verbose_name="Receipt name")  #: Receipt name
    ....

    # Auditing
    owner = models.IntegerField(verbose_name="Owner", choices=[('', '')]   _choices_user())
  

Поскольку настройка нескольких баз данных не поддерживает прямые ссылки, мы используем целочисленное поле для владельца, а бизнес-логика обрабатывает целостность.

Проблема заключается в _choices_user(), который задает запрос для отсутствующей таблицы. Чего я не понимаю, так это почему django не создает таблицу auth_user при первом запуске. Если я удалю приложение с вызывающей моделью, тестовая среда будет работать без каких-либо проблем.

Есть идеи, как это можно исправить?

Спасибо!

Редактировать: я создал одну настройку базы данных и попробовал то же самое. К сожалению, он выдает ту же ошибку! Теперь я в замешательстве. Может ли кто-нибудь проверить это тоже? Создайте модель с помощью метода _choices_user и запустите test.

Комментарии:

1. Добавлен отчет об ошибке в проекте django code.djangoproject.com/ticket/22864#ticket .

Ответ №1:

Вы можете вручную выбрать базу данных. Просто вызовите using() . Метод using() принимает один аргумент: псевдоним базы данных, в которой вы хотите выполнить запрос.

 def _choices_user():
    users = User.objects.using('default').all()
    .....
    .....
  

Документы Django 1.7

Комментарии:

1. Звучит многообещающе! Протестирую его, но сначала нужно обновить до django 1.7.

Ответ №2:

Это не совсем идеальный ответ, но единственный способ в настоящее время:

Модель (удаленные варианты):

 class CustomerReceipts(models.Model):
    # General
    receipt_name = models.CharField(max_length=20, verbose_name="Receipt name")  #: Receipt name
    ....

    # Auditing
    owner = models.IntegerField(verbose_name="Owner")
  

Администратор:

 class CustomerReceiptsAdminForm(forms.ModelForm):
    class Meta:
        model = CustomerReceipts

    users = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(CustomerReceiptsAdminForm, self).__init__(*args, **kwargs)
        owner = self.instance.owner
        usersAll = User.objects.all()
        usersAll = usersAll.order_by('id')
        available_choices = [(e.id, e.username) for e in usersAll]
        self.fields['users'].choices = available_choices
        self.fields['users'].initial = owner

class CustomerReceipts(admin.ModelAdmin):
    fields = ('abc', 'users')
    list_display = ('abc', 'get_user')

    form = CustomerReceiptsAdminForm

    def save_model(self, request, obj, form, change):
        obj.owner = form.cleaned_data['users']
        obj.save()

    def get_user(self, obj):
        return User.objects.get(id=obj.owner).username
    get_user.short_description = 'User'
  

Это обработает все отображение в представлении администратора и выберет нужного клиента при редактировании.