Вы можете использовать аннотацию Exists
.
from django.db.models import OuterRef, Exists
class NewModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
queryset = super(NewModelAdmin, self).get_queryset(request)
old_model = OldModel.objects.filter(old_path=OuterRef('url'))
return queryset.annotate(
has_old_model=Exists(old_model),
)
class NewModel(models.Model):
...
@property
def is_redirected(self):
if hasattr(self, 'has_old_model'):
return self.has_old_model
# Fall back to previous method if you're worried
# you don't have all paths covered.
return OtherModel.objects.filter(old_path=self.url).exists()
Я использовал его для плагинов к приложениям ... таким образом, ваше основное приложение может вызывать фабрику классов создать конкретный плагин, реализующий некоторый интерфейс, который вы разработали в своем основном приложении. Таким образом, вы можете кодировать основную часть вашего приложения, даже не зная, что будет подключено.
Я только что использовал его в приложении планирования, где запланированные задачи находятся в отдельных сборках, а планировщик делает ничего не знаю о задачах ... Он получает имя сборки, в которой задана задача, из внешнего источника, а затем динамически загружает сборку, создает экземпляр класса в этой сборке с использованием четко определенного интерфейса. Метод фабрики в планировщике, который принимает имя сборки в качестве входного параметра, возвращает экземпляр класса в загруженной сборке ...
... но существует так много вариантов использования и способов использования ... этот шаблон ,
Предположим, у вас есть очередь, содержащая объекты типа task
.
Теперь вы можете создавать подклассы task
по разным причинам. Если вы загружаете свои задачи из какого-либо источника, например из базы данных, вы можете использовать фабрику, чтобы определить, какой тип задачи загружать.
Например:
private IEnumerable<Task> GetTasks(DataTable Table){
Task NewTask;
foreach(DataRow Row in Table){
switch(tasktype){
case tasktypes.TaskTypeA:
NewTask = NewTaskA(...);
break;
case TaskTypes.TaskTypeB:
NewTask = NewTaskB(...);
break;
...
}
yield return NewTask;
}
}
Позже вы можете вызывать виртуальные методы для задач в вашей очереди, например «потреблять» или «обрабатывать», например.
Преимущество фабричного подхода (в данном случае) состоит в том, что вам нужно только один раз включить тип задачи (при создании задачи) и позволить полиморфизму обрабатывать большинство всего. еще.
а именно в одном из 2 случаев:
По общему признанию, необходимость в фактическом использовании более болезненных деталей реализации, описанных шаблоном, была устранена благодаря тому, как работает C # , но моя функциональность SQL DAL передает фабрики объектов (и команды SQL) служебным функциям, которые используют фабрики для генерации объектов. Если бы я не использовал C #, я мог бы вместо этого использовать явный фабричный класс, который генерировал объекты.
Заводской шаблон очень полезен для отображения емкости в соответствующий обработчик.