Несколько экземпляров приложения django, поддерживает ли django это - PullRequest
5 голосов
/ 14 января 2012

Я написал простое приложение для обратной связи в django. Это не особенно сложно, в основном это позволяет аутентифицированным пользователям написать отсканированное сообщение со строкой темы и отправить это сообщение через форму. Затем я позволяю пользователям из выбранной группы просматривать отправленные пользователями отзывы. В будущем я могу добавить больше функциональности, но сейчас она делает то, что я хочу.

Вот мой вопрос, у сайта, который я создаю, есть несколько мест, где я хотел бы использовать приложение обратной связи, например, у меня есть "что вы думаете о сайте?" вид страницы на /dev/feedback/ У меня также есть одна для обратной связи со службой поддержки по адресу "/ support / feedback /". В настоящее время я только что скопировал код из моего mysite.apps.dev.feedback в mysite.apps.support.feedback.

Проблема в том, что теперь созданы две отдельные копии одного и того же кода. Несмотря на то, что только что написали приложение, две версии уже начинают расходиться, что раздражает. Мой вопрос заключается в том, как просто создать несколько экземпляров одного и того же приложения на сайте django с различными моделями баз данных?

Некоторые ресурсы, которые я нашел связанными, но бесполезными: https://docs.djangoproject.com/en/dev/topics/http/urls/ и Сторнирование URL-адресов с пространством имен в Django: несколько экземпляров одного и того же приложения Первая страница не предлагает много информации по этой проблеме и На второй странице представлены несколько грязные и непрактичные решения, которые кажутся как не связанными, так и более трудоемкими, чем их ценность. Есть ли правильный способ реализовать несколько экземпляров одного и того же приложения django?

Ответы [ 3 ]

3 голосов
/ 14 января 2012

Подход к одной модели

Я бы лично попытался сохранить это как одно приложение и иметь представление, которое может обрабатывать публикации из разных мест / помечать их соответствующим образом.

Как говорит С. Лотт, это путь . Я предлагаю альтернативные варианты, если вам интересно узнать, как сохранить код в одном месте в других ситуациях.

Например, вы можете добавить в свою модель поле category, настроить один URL-адрес conf, который принимает аргумент в URL-адресе, такой как /(?P<category>\w+/feedback/$, и чтобы представление просто помечало обратную связь соответствующей категорией.

class MyForm(forms.ModelForm):
    class Meta:
        model = Feedback

def my_view(request, category):
    form = MyForm(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            feedback = form.save(commit=False)
            feedback.category = category
            feedback.save()
            return http.HttpResponse("Thanks for posting!")
    return render(request, "mytemplate.html", {'form': form})

# urls.py
(r'^(?P<category>\w+)/feedback/$', 'my_view')

# user can visit dev/feedback or support/feedback and the feedback will be tagged appropriately

Абстрактный базовый класс

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

У вас будет одна абстрактная модель (без таблиц), на которой будут основываться ваши "реальные" модели в отдельных приложениях.

Динамически генерируемые представления

Если вам нужны отдельные модели, вы можете написать динамически построенное представление.

def view_generator(model_class):
    class MyForm(forms.ModelForm):
         class Meta:
              model = model_class

    def my_view(request):
        form = MyForm(request.POST or None)
        if request.method == 'POST':
            if form.is_valid():
                form.save()
                return http.HttpResponse("Thanks for posting!")
        return render(request, "mytemplate.html", {'form': form})
    return my_view


# urls.py
from foo import view_generator

(r'^my_first_feedback_form', view_generator(Model1))
(r'^my_second_feedback_form', view_generator(Model2l))
2 голосов
/ 14 января 2012

как создать несколько экземпляров одного и того же приложения на сайте django с различными моделями баз данных?

Ты не должен.

Вы просто используете модель приложения обратной связи в двух других приложениях с помощью простого from feedback.models import Feedback.

Тогда ваше приложение support может создавать, извлекать, обновлять и удалять объекты Feedback.

Ваше приложение dev также может создавать, извлекать, обновлять и удалять объекты Feedback, поскольку оно импортировало модель.

Это все, что требуется: import.

1 голос
/ 16 января 2012

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

Сначала в мой mysite.apps.feedback.models файл я положил

class Feedback( models.Model ):
   subject = models.TextField( max_length=100 )
   body = models.TextField( max_length=100 )
   # Some other stuff here...
   # Finally I used the suggestion above and created a field which I 
   # use to label each entry as belonging to a specific instance of the app.
   instance_name = models.TextField( max_length=20 )

В мой mysite.apps.feedback.views файл я положил

def save_message( request, instance_name ):
    if request.method == 'POST':
        form = FeedbackFrom( request.POST )
        if form.is_valid():
            form.instance.instance_name = instance_name
            form.save()
            return render("feedback/thanks.html")
         else:
             return render("feedback/submit.html", {'form':form })
     else:
         return render("feedback/submit.html",{'form':FeedbackForm()})

@user_passes_test( is_staff )
def all_messages( request, instance_name ):
    messages = Feedback.objects.filter( instance_name = instance_name )
    return render("feedback/view_all.html",{'feedback':messages} )

В мой mysite.apps.dev.urls файл, который я положил

url(r'^feedback/', include('mysite.apps.feedback.urls'),
    {'instance_name':'dev'}),

В моем файле mysite.apps.support.urls я поместил

url(r'^feedback/', include('mysite.apps.feedback.urls'),
    {'instance_name':'support'}),

Это разделит сообщения обратной связи по экземпляру приложения.Обратите внимание, что мой реальный код более сложный, но этого должно быть достаточно для тех, у кого похожая проблема, чтобы довольно быстро найти решение и запустить его.Надеюсь, что это полезно для любого в подобной ситуации.Еще раз спасибо Yuji Tomita за предложения, на которых основано это решение.

...