Используйте обратную связь :
{% for role in current_project.role_set.all %}
{{ role.job.name }}
{{ role.user.username }}
{% endfor %}
РЕДАКТИРОВАТЬ:
Есть ли способ сделать это в модели или в представлении вместо (не используя другой переменная), как prefetch_related? Потому что метод в шаблоне генерирует несколько дубликатов SQL запросов.
blockquote>IIRC вы можете применить
prefetch_related
иselect_related
к набору запросовProject
в вашем представлении, т.е.qs = Project.objects.prefetch_related(....).select_related(...) current_project = qs.get(pk=...)
, но это из памяти, и у меня нет времени перепроверить это прямо сейчас ...
Я бы предложил использовать Iterable
, Collection
или List
как тип параметра.
IMO, коллекции следует отдавать предпочтение ссылочным массивам. Если у вас есть массив , Arrays.asList
хорошо выполнит преобразование. Arrays.asList
позволяет получить и установить обратно в массив, но, очевидно, не «структурные» модификации, которые могли бы изменить длину массива.
myFun(Arrays.asList(arr));
Возможно, вам придется использовать групповые символы в крайних / общих случаях. [1246 Следует отметить, что Collections.toArray
и Arrays.asList
работают немного по-разному. asList
сохраняет исходный массив для поддержки коллекции, поэтому изменения в коллекции будут отражены в массиве. Коллекция. toArray
делает (мелкую) копию данных коллекции. Создание копии часто является тем, что вы хотели бы в любом случае, если вы возвращаете массив. Асимметрично, если вы передаете в качестве аргумента, вы обычно не копируете (если не сохраняете как поле).
вы не можете , java Arrays не реализует Iterable:
public static int sum(Iterable<Integer> elements) {
int s = 0;
for (int i : elements) {
s += i;
}
return s;
}
public static void main(String[] args) {
L1: System.out.println(sum(1,2,3));
L2: System.out.println(sum(Arrays.asList(1,2,3)));
L3: System.out.println(sum(new int[] { 1,2,3 }));
}
это приводит к двум ошибкам времени компиляции в (L1 и L3); так что вы должны разработать свой метод для приема Iterable (Collections) и / или Array, по крайней мере один метод должен выполнить некоторое преобразование (в / из массива)
ВОЗМОЖНОЕ РЕШЕНИЕ :
вы можете попробовать использовать адаптер:
public class ArrayIterator<T> implements Iterator<T> {
private final T[] array;
private int i;
public ArrayIterator(T[] anArray) {
array = anArray;
i = 0;
}
public boolean hasNext() {
return i < array.length;
}
public T next() {
return array[i++];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
private static int sum(final Integer ... elements) {
return sum(new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new ArrayIterator<Integer>(elements);
}
});
}
вам следует обращать внимание только при работе с примитивными массивами; когда вы используете только ссылочный объект (ваш случай) ArrayIterator + анонимный класс - это круто
надеюсь, что это поможет
Используйте Iterable
. Вот для чего это.
Как вы сказали, Iterable
не будет обрабатывать массивы.
Вы не хотите использовать несколько методов, оборачивающих друг друга. Это исключает Arrays.asList
и Collection.toArray
.
Таким образом, ответ на ваш вопрос - нет, пути нет. Но если вы можете использовать списки
, зачем вам когда-либо использовать массивы?
Я все равно остановлюсь здесь на Iterable
. Мне нравится это лучше, чем Collection
, потому что в прошлом у меня были классы, которые реализовали Iterable
, но не были коллекциями; это облегчало им ленивый поиск значений по мере необходимости, и я мог использовать цикл foreach для них.
Есть небольшая известная особенность Java Generics в Java 1.5+, где вы можете использовать расширяет Subtype>
в ваших вызовах методов и конструкторах. Вы можете использовать extends Object>
, и тогда все, что с ними связано, будет иметь доступ только к методам Object. На самом деле вам может понадобиться что-то вроде этого:
List<? extends MyCrustaceans> seaLife = new ArrayList<? extends MyCrustaceans>();
MyShrimp s = new MyShrimp("bubba");
seaLife.add(s);
DoStuff(seaLife);
...
public static void DoStuff(List<? extends MyCrustaceans> seaLife)
{
for (MyCrustaceans c : seaLife) {
System.out.println(c);
}
}
Итак, если у вас есть базовый класс (например, MyCrustaceans), вы можете использовать любые методы этого базового класса в DoStuff (или в классе Object, если ваш параметр ] extends Object>
). Есть похожая особенность super MyType>
, где он принимает параметр, который является супертипом данного типа, а не подтипом. Существуют некоторые ограничения на то, для чего вы можете использовать «расширяет» и «супер» таким образом.
public static void myFun(Collection<MyClass> collection) {
for (MyClass mc : collection) {
// Stuff is processed here
}
}
Краткий ответ: нет, не существует единой сигнатуры метода, которая бы безошибочно принимала тип Iterable и массив. Очевидно, вы могли бы просто принять Object
, но это также было бы хаком.
Ответ с длинным ответом: поскольку расширенный для
-loop эффективно определяется дважды (один раз для массивов). и один раз для Iterable
), вам также потребуется предоставить два перегруженных метода:
public static void myFun(SomeClass[] array) {
for (SomeClass sc : array) {
doTheProcessing(sc);
}
}
public static void myFun(Iterable<? extends SomeClass> iterable) {
for (SomeClass sc : iterable) {
doTheProcessing(sc);
}
}
Хотя источник этих двух методов выглядит точно так же, вам нужно определить его дважды (если только Конечно, вы оборачиваете массив в свою собственную итерируемую
, как обрисовано в общих чертах @dfa).