• Как правильно связать php сайт с mysql?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    На частные вопросы ответили в комментариях, поэтому ответим на вопрос из заголовка.

    Чтобы соединить сайт с mysql, в РНР вообще-то есть два API - mysqli и PDO. Несколько лет назад с mysqli вообще невозможно было нормально работать, но на данный момент они выровнялись, хотя PDO все равно удобнее, по трем причинам
    1. Единый интерфейс при работе с различными СУБД (неактуально, если mysql для нас является синонимом слова база данных)
    2. Набор функций-хелперов для получения данных из БД в различных форматах (при желании легко воспроизводится вручную)
    3. Именованные плейсхолдеры (для некоторых это главная причина использовать PDO)

    Но в целом, как я говорил выше, сейчас можно использовать любое API. Главное - не использовать тот древний говнокод, который приведён в вопросе.

    1. Создаём файл`config.sample.php` куда кладем все настройки приложения, в том числе базы данных
    return [
    	'db' => [
    		'host' => '127.0.0.1',
    		'username' => '',
    		'password' => '',
    		'dbname' => '',
    		'port' => 3306,
    		'charset' => 'utf8mb4',
    	],
    ];

    2. В файле, который включается во все скрипты сайта, добавляем код
    if (!file_exists('config.php'))
    {
    	throw new \Exception('Create config.php based on config.sample.php');
    }
    $config = require 'config.php';

    3. И дальше в этом же файле пишем собственно нормальный код подключения к БД
    либо к mysqli
    // включаем режим информирования об ошибках
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // подключаемся к серверу
    $dbc = $config['db'];
    $db = new \mysqli($dbc['host'], $dbc['username'], $dbc['password'], $dbc['dbname'], $dbc['port']);
    // не забываем установить кодировку, чтобы не было ошибок с кракозябрами
    $db->set_charset($dbc['charset']);

    либо к PDO
    $options = [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    $dbc = $config['db'];
    $dsn = "mysql:host=$dbc[host];dbname=$dbc[dbname];charset=$dbc[charset];port=$dbc[port]";
    $pdo = new \PDO($dsn, $dbc['username'], $dbc['password'], $options);

    После того как будет освоена работа с системой контроля версий (а по-хорошему это надо было сделать уже давно) добавляем config.php в файл .gitignore
    Таким образом на каждом хосте, где исполняется этот код, будет собственный файл с настройками, создаваемый по образцу из config.sample.php

    Да, и Очень Важное Дополнение:
    почему нельзя сделать 1 соединение для сайта и не тратить каждый раз время на коннект к БД?

    Никогда не следует переживать по поводу воображаемых проблем. Вот только когда создание коннекта каждый раз станет реальной проблемой, только тогда и начинать переживать по этому поводу и искать пути решения (спойлер: никогда).
    Ответ написан
    14 комментариев
  • Как провести соответствие между строкой и классом с точки зрения SOLID?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это всё очень плохо.
    В первом варианте человек должен знать, как мяукают кошки, а в последнем "правильном" варианте человек трогает не кошку, а кошачий голос(?!).
    В "идеальном" варианте опять же выбирается не животное, которое надо погладить, а его голос.

    Чтобы следовать принципам солид, надо понять в первую очередь ЗАЧЕМ это всё делается.
    А делается это для того чтобы уменьшить связность. Чтобы класс, использующий какой-либо функционал, не знал деталей его реализации. И, соответственно, мы могли бы менять реализацию без опасения поломать что-то в классе-пользователе.

    При этом extends, кроме как от абстрактного класса, эту связность всегда увеличивает.
    И его надо избегать. А использовать принцип Composition over inheritance. То есть нужный функционал получать не наследованием, а передачей независимых функциональных модулей в виде параметров.

    Соответственно, нам надо сделать иерархию: голос - животное - потрогать.
    И вот теперь у нас хоть голос, хоть животное, будут открыты для каких угодно изменений, до тех пор пока они поддерживают публичный контракт.
    / ******* голоса *******/
    abstract class VoiceEngine {
    	public function getVoice() {}
    }
    class CatVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Meow!";
    	}
    }
    class DogVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Bark!";
    	}
    }
    class HumanVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Да пошёл ты!";
    	}
    }
    / ******* животные *******/
    abstract class Animal {
    	public function __construct(public VoiceEngine $voiceEngine) {}
    	public function say() {
    		echo $this->voiceEngine->getVoice();
    	}
    }
    class Cat extends Animal{}
    class Dog extends Animal{}
    class Human extends Animal{
    	public function touchAnimal(Animal $animal) {
    		$animal->say();
    	}
    }
    / ******* исполнение *******/
    $cat = new Cat(new CatVoiceEngine());
    $dog = new Dog(new DogVoiceEngine());
    $human = new Human(new HumanVoiceEngine());
    $human->touchAnimal($cat);
    $human->touchAnimal($dog);
    $human->touchAnimal($human);


    После того как я, раздуваясь от гордости, написал этот ответ, до меня вдруг дошло что на вопрос-то я так и не ответил.
    Соответственно, задачу выбора животного возлагаем на отдельную сущность:

    class AnimalFactory {
        public static function create($type) {
            return match($type) {
                'cat' => new Cat(new CatVoiceEngine()),
                'dog' => new Dog(new DogVoiceEngine()),
                'human' => new Human(new HumanVoiceEngine()),
            };
        }
    }
    $human = new Human(new HumanVoiceEngine());
    $human->touchAnimal(AnimalFactory::create('cat'));

    В итоге мы вернулись к тому же кейсу (match - это улучшенный case), но при этом у нас всё разделено, и каждый класс занимается строго своим делом.
    Ответ написан
  • Как изменить версию php, которую использует веб-сервер?

    Stalker_RED
    @Stalker_RED
    Очевидно, у вас несколько версий php установленно одновременно, и сервер использует версию отличную от той, что у вас в консоли.
    Команда php -i выдаст вам консольный аналог phpinfo, где можно посмотреть путь к php.ini
    также могут помочь команды типа whereis php или which php, или константа PHP_BINARY (в консоли php -r "echo PHP_BINARY;") .
    Скорее всего они выдадут /usr/bin/php

    Затем в конфиге nginx укажите тот-же бинарник, который используется в cli.
    Ответ написан
    Комментировать
  • Как изменить версию php, которую использует веб-сервер?

    @sand3001
    Всего по немногу
    Nginx не умеет самостоятельно обрабатывать php, поэтому использует "посредника" (например fastcgi php-fpm). Посмотреть текущего "посредника" можно через вывод phpinfo (поле Server API). Настроить версию можно, указав в директиве fastcgi_pass путь к нужному сокету.
    Ответ написан
    Комментировать
  • Доступ ко многим через отношения. Как подобраться?

    dlnsk
    @dlnsk
    ПК Партнер 01.01 -> ПК Поиск -> IBM PC
    Модели (и отношения соответственно) нужны в том случае, когда вы собираетесь работать с ними как с моделями, т.е. изменять, сохранять, использовать другую "магию". Но если вам нужно получить данные, которые вы не собираетесь изменять (отобразить, посчитать, использовать в других запросах), то используйте для этого обычный Query Builder (https://laravel.com/docs/8.x/queries) и делайте любые join'ы, какие заблагорассудится.
    Имейте в виду, что не всякий запрос возможно (или удобно) делать с помощью Eloquent, особенно когда речь идет о функциях агрегирования.
    Ответ написан
    1 комментарий
  • Попинайте 2. Удалось ли исправить устаревший код, который забраковал работодатель?

    @Flying
    Согласен с FanatPHP по поводу того что изменения, по сравнению с предыдущим вариантом, просто колоссальные, поздравляю!

    Однако сразу видны те направления движения которые стоит рассматривать в первую очередь:

    1. Вам стоит лучше изучить возможности языка. PHP развивается очень динамично и в 7-й версии было добавлено огромное количество вкусных возможностей, про них стоит знать и ими стоит пользоваться
    2. Необходимо лучше изучить имеющуюся на данный момент экосистему готовых пакетов, это позволит вам использовать готовые, проверенные решения вместо изобретения своих велосипедов. Подключение Twig - первый шаг, но далеко не последний
    3. Вам обязательно стоит посвятить время изучению кода популярных проектов. Это многое может рассказать вам о подходах к решениям, паттернах и т.п. Конечно, параллельно нужно будет выяснять значения массы используемых терминов чтобы лучше понимать происходящее, это тоже пойдёт вам на пользу.
    4. Смотрите как развиваются другие технологии, которые вы используете, таблицами сейчас не верстают :)
    5. Рекомендую рассмотреть вариант использования для написания кода нормальной IDE, к примеру PHPStorm, это существенно улучшит вашу производительность и убережёт от массы ошибок


    Теперь более предметно:

    Оформление кода:

    Вы утверждаете что код соответствует PSR-2 (кстати, актуальный - PSR-12), однако есть мелкие огрехи (раздел 2.2).

    Оформление composer.json:

    Лучше указывать требования к платформе, в вашем случае - как минимум версию PHP т.к. platform requirements проверяются Composer'ом при установке.

    Поскольку ваш проект - не библиотека, то composer.lock тоже должен быть частью репозитория.

    Про настройки autoload'а вам уже сказали, обращу только внимание на то что сейчас структура репозитория отражает PSR-0, а не актуальный PSR-4, при использовании PSR-4 ваш код проекта лежал бы в src.

    Организация репозитория

    Код проекта должен лежать за пределами web root, поэтому вам явно не хватает папки public с единственным index.php

    Конфигурация

    Конфигурирование через константы - весьма устаревший подход. К примеру представьте что вы разворачиваете этот код на production сервере и вам нужно сменить данные для подключения к базе данных не создавая локальных изменений в рабочей копии. Сейчас у вас это не получится. Выход: читаем про
    12 factor app и, в частности, раздел config, а затем подключаем в проект, к примеру, vlucas/phpdotenv или symfony/dotenv

    Сервисы

    Использование bootstrap.php - хорошо, но для организации работы с сервисами сейчас как правило используются dependency injection контейнеры, даже PSR-11 для них есть. В текущем виде ваш подход слабо расширяем, а передача сервисов через глобальные переменные - так себе идея по многим причинам.

    Понятно что вворачивать DI container для примера на три файлика - overkill, но с самим подходом вам следует ознакомиться. Из реализаций самая популярная сейчас - symfony/dependency-injection, но есть и альтернативы.

    Автолоадер

    Про autoload.php вам уже сказали, вместо него стоит корректно конфигурировать автозагрузку в composer.json и полагаться на то что Composer вам сгенерирует. Он ведь умеет всё это и оптимизировать при необходимости.

    Внешние пакеты

    Для новых проектов рекомендуется выбирать актуальные и поддерживаемые версии пакетов. Хотя Twig 1.x ещё поддерживается, тем не менее актуальная версия - 3.x.

    Обработка ошибок

    Попробовать сделать это самостоятельно, безусловно, полезно чтобы лучше разобраться как это работает, но для реальной работы лучше полагаться на проверенные решения, к примеру filp/whoops или symfony/error-handler

    Типы данных

    Важно помнить что PHP с версии 7.0 поддерживает указание скалярных типов для аргументов и
    возвращаемых значений, с 7.1 - nullable типы и class constant visibility, а с 7.4 - типизированные свойства. Всё это гораздо надёжнее чем описание типов через аннотации и этим стоит пользоваться.

    Также повсеместно в коде используется нестрогое сравнение, тогда как очень желательно всегда использовать строгое (документация).

    Data Objects

    Сейчас Place и PlaceFilter по сути являются data объектами т.е. они не содержат самостоятельной логики, а просто переносят некие данные. При этом оба этих класса имеют пустые конструкторы (которые, кстати, лучше убирать), а загрузка данных организована через setter методы. Это позволяет изменить данные в них в произвольные моменты времени что вряд ли является желаемым поведением. Вместо этого подобные объекты лучше организовывать в виде immutable объектов (статья с примерами) чтобы не позволять ненужного нарушения целостности данных. Альтернативно, к примеру, для PlaceFilter может лучше подходить использование паттерна
    Builder
    , хотя в википедии не самый лучший пример.

    Именование

    Все мы, надеюсь, помним про две сложные проблемы, здесь как раз проявляется вторая из них. PlaceFactory ну никак не является реализацией одноимённого паттерна.

    Оптимизации

    Понятно что это мелочи, но явно видно что компиляцию запросов (1, 2) можно кэшировать вместо того чтобы перекомпилировать каждый раз.

    References

    PDOStatement::bindParam() принимает аргумент $variable как reference, а в коде в этот аргумент передаётся выражение что недопустимо.

    Английский язык

    Я специально почти везде по тексту давал ссылки на информацию на английском языке т.к. он - основной язык в нашей индустрии и его важно знать и использовать.
    Ответ написан
    3 комментария
  • Что нужно делать на практике в JavaScript, чтобы его понимать?

    approximate_solution
    @approximate_solution
    JS Developer. Angular\React\Vue\Ember
    То что вам скинули - это замечательно конечно. Но для себя вопрос задайте для начала, для чего вам нужен JS - если учиться решать задачки - то всё что выше вам хватит с головой. Если вы планируете разрабатывать с помощью JS интерфейсы, как можно скорее изучить базу, и начинать делать несложный пет проект.
    слайдер, выпадающее меню
    - это капля в море.
    Пет проект для JS джуна - вот вам пример правильно поставленной цели. Придумываете для себя задачу, и по мере решения и написания массы костылей - у вас придет понимание языка, через кровь, слезы и постоянное гугление. Язык учиться именно так, а не через монотонное решение задач.
    Каждую мелочь, непонятную деталь - гуглить, задавать тысячи вопросов, читать книги - и ваш разум будет озаряться.
    Ответ написан
    Комментировать
  • Почему PHP теряет популярность?

    AleksandrB
    @AleksandrB
    Совсем недавно вывел "Hello world"
    PHP не мода, php - классика, а классика никогда не умирает. Если умрет php, то умрут все остальные языки backend разработки потому что появится что-то такое, что сможет в разы превзойти пхп в простоте, скорости и удобстве, на данный момент что джава, что питон, что руби +- одинаковые, каждый подходит для своих целей. Тот же питон выбирают из-за простоты интеграции нейронных сетей, но если говорить не о узких, а о главных параметрах (функционал, скорость и тд) все популярные бэк языки более или менее одинаковые смотрите те же сухие графики.
    А о уменьшении вакансий - глупость несусветная. трын тут приведена статистика за 2018 год и обоих графиках по вакансиям лидирует в сравнении с java/python PHP, при том на первых двух пишут как бэкэнд, так и миллион других штук. А на втором графике и вовсе пхп опережает js (единственный язык в самой популярной сфере разработки).

    А вот если речь идет о реально крупных компаниях (amazon, google...) там как раз предпочитают python из-за выше упомянутой простоты интеграции нейросетей, а java из-за стабильной поддержки сверх высоких нагрузок.

    Меньше слушайте диванных экспертов, пхп предрекают смерть с 00-х годов, что то он слишком долго дергается для мертвеца.
    Ответ написан
    1 комментарий
  • Почему PHP теряет популярность?

    @Kirill-Gorelov
    С ума с IT
    Я был в обсуждениях с некоторыми парнями на счет скорости и удобства и бла бла бла работы на php.

    Мне один парень сказал, что php скоро сдохнет. Но ему ответил второй программист:
    Он уже дохнет столько лет, что уже выпустили "предсмертную"(сарказм) 7 версию(на момент обсуждения). А сейчас уже готовят 8 версию, которая будет еще быстрее.

    И мое мнение.
    Php не умрет никогда. Потому что всегда будут две стороны халявщиков.
    1. Которая хочет быстро что-то выучить и на этом заработать.
    2. Те кто хочет быстро и дешево заказать сайт.
    И вот эти две стороны будут генерировать, назовем это, спросом на этот язык.
    Конкретно сейчас я не беру в обсуждения профессиональные сайты, которые действительно крутые и действительно достойные внимания и людей которые посвятили этому языку львиную долю своего времени.
    Ответ написан
    8 комментариев
  • Почему PHP теряет популярность?

    anton_reut
    @anton_reut
    Начинающий веб-разработчик
    Никогда не ведитесь на уговоры разрабатывать какой то веб проект на каком то экзотичном языке, например Питоне или Яве, в результате вы получите костыльный долгострой и дефицит программистов которые будут готовы над ним работать.
    Это как в моде - есть всякое эпатажное дерьмо для показов на подиуме, а есть повседневные джинсы с рубашкой, все любят обсуждать эпатаж но носят джинсы.
    Ответ написан
    26 комментариев
  • Как не пускать на сайт при включенном adblock/ublock и прочее?

    @d-stream
    Готовые решения - не подаю, но...
    Большая часть пользователей адблокеров просто тут же покидает сайты-попрошайки, если их попрошайничество хоть как-то мешает. Бывают конечно редкие сайты-исключения, на которых блокировщики отключают.
    Но чтобы этого добиться - надо быть ресурсом типа хабра или Майкрософта.
    Ответ написан
    14 комментариев
  • Как не пускать на сайт при включенном adblock/ublock и прочее?

    @uroot
    Для того, чтобы обойти такие определения на наличие adblock/ublock достаточно просто отключить JS. Но здесь дело в другом. Если лично я вижу такой сайт, то я просто на него больше никогда не вернусь или тем же adblock-ом заблокирую всплывающее окно "Отключите adblock".

    И так сделают многие - они просто не вернутся на ваш сайт.
    Ответ написан
    14 комментариев
  • Что прочитать по ООП и паттернам для веб-разработки на PHP?

    e20860
    @e20860
    Работал с СУБД, осваиваю WEB
    Сам сейчас пытаюсь перейти на веб-разработку после Visual FoxPro. Корплю над учебниками. На мой скромный взгляд:
    1. книга Мэтта Зандстры "PHP Объекты, шаблоны и методики программирования". Вполне конкретная и доходчивая книжка.
    2. Курс по созданию собственного фреймворка. 29 занятий с нуля. https://www.youtube.com/watch?v=nGHfiWjIDr8&list=P...
    Мне помогают очень. Только книгу надо читать с опережением относительно курса...
    Ответ написан
    Комментировать
  • Что обязательно нужно знать в PHP и что посоветуете выучить?

    @anton99zel
    29а класс средней школы №7
    Частично согласен, и вот что в целом получается:
    Грубо говоря, рынок "создателей сайтов" делится на два лагеря: школьники, готовые за 500 рублей за 2 часа состряпать что-либо из готового шаблона, и профессиональные фрилансеры и веб-студии. Заказчики, к счастью не все, но все же ищут тех, кто сделает хорошо и очень дешево. Но потом все равно такие заказчики идут на биржу в целях найти тех, кто исправит косяки школьников, а также реализует все "хотелки". Чаще вижу не тех кому нужен сайт, а тех кому нужны люди с напильником. Особенно подобное можно наблюдать в сфере интернет-магазинов, когда каждый школьник может установить cms, а потом когда нужно настраивать разного рода функционал, то школьники уже в силу своих знаний, ничего не могут. Это касается различного рода: работы с интернет платежами, синхронизации, доработка различных фильтров, написание собственных разработок, модулей.

    Потому, заказчикам более интересен человек не со знаниями голого php, а скорее человек, который может найти решение той или иной задачи, написать код и обвесить все это стилями и скриптами. Нужно и смежные "науки" изучать. И не столько книгами, сколько в практике.

    На мой взгляд, половина тех, кто откликается на задачи на фрилансе, вообще не представляют как делается та или иная задача. Когда то давно, я размещал на фрилансе задачу: нужно было IPB подружить с Битриксом, сделать единых пользователей и авторизация. Из десятка откликнувшихся так и никто не смог сделать. Пришлось самому разбираться, буквально дня три и у меня получилось, но в те времена, для меня это было как увлечение.

    Читайте хабру, тостер, сделайте свой тестовый сайт и на его базе придумывайте новый функционал, это будет теория с практикой. Задачки можно подсматривать тут или на фрилансе. Но в целом, тот багаж знаний, который вы описали, достаточен, чтобы начать маломальски где-либо работать, но расти нужно каждый день. Мне кажется в данной сфере - всю жизнь учишься и работаешь.
    Ответ написан
    Комментировать
  • Переход из 1С в web-разработчики (PHP ) в 35 лет. С чего начать и реально ли?

    AlexeyGfi
    @AlexeyGfi
    YouTube >>> Битриксоид из Колхоза
    Больше 10 лет работаю под Битриксом. Мне очень нравится то, что в этой работе нужен целый стек знаний. Начиная от настройки апача и нжинкса (у меня свой сервер на Хетцнере) и до вёрстки. Прям прёт от кайфа.

    Этот год начал вникать в новое ядро (а там уже ORM), начал восполнять недостаток знаний. Ниточка за ниточкой... — просмотрев видео-курс по Ларавел понял, что моё мировоззрение дало трещину. Насколько там всё строго и по полочкам, в противовес анархии внутри Битрикса. Но у битрикса шикарное лицо. CMS прокачана так, что удобно как заказчику, так и обслуживающей команде. Вряд ли какая CMS сможет угнаться. Но внутренности... Мама дорогая. Хочется скрестить Ларавел и Битрикс (CMS).

    Есть надежда, что новое ядро привнесёт какую-то строгость, но, увы, Битриксы не культивируют "эко-культуру". То есть тренда быть стильным, правильным, структурным — нет. Порог входа опущен настолько, что можешь писать лапшой, можешь прикручивать свои шаблонизаторы. Вообще твори что хочешь. Битрикс ограничивается необязательными рекомендациями.

    Ища выход стремлению "хочу большего" завёл профиль на апворке и логично задумался: а что я могу предложить? То есть сначала была шальная мысль выходить на full-stack заказы c Битриксом, но, блин, после Ларавелл я уже не уверен. Если переходить (менять тех заказчиков, которые уже есть), то на солидный уровень (по задачам, в первую очередь). А для этого нужно понимание: к чему душа лежит (выбор технологии) и что востребовано (однозначно могу сказать, что буду копать Ларавел — уже и мини-проекты придумал; из фронт-энда буду пробовать пилить Вью, но пока что нет жёсткой мотивации: чистый css/js никто не отменял). А значит метод проб и ошибок. Пока не определился — держать ушки на макушке и анализировать входящий поток, не особо отвлекаясь от текущих дел, потому что так можно и загнуться (а на плечах семья, дети).

    Пытаясь понять, «как оно», — запустил и небольшой оффлайн бизнес с продажей через Интернет. Есть опыт запуска своих проектов и этот путь мне кажется наиболее перспективным для удовлетворения жизнью: сразу делаешь то, что легко согласовывать (с самим собой =), за ошибки платишь сам, можно делать неспеша (некоторые решения должны вызреть внутри), а можно упасть и прям не вставать пока не закончил — делаешь-то для себя, а это совсем другой настрой.

    Но чем хорошо (полезно) по-фрилансивать: остаёшься в курсе новинок, не оседаешь в своей тине и не разучиваешься шевелиться. По сабджу — держать нос по ветру, пробовать разные задачки, пока не придёт чёткое понимание.
    Ответ написан
    Комментировать
  • Должен ли back-end разработчик уметь верстать?

    @uniquenicknqame
    На Питоне нужно, даже очень.
    А в серьезных коммандах есть очень четкое разделение ролей: каждый занят своим и делает это наилучшим образом.
    Ответ написан
    Комментировать
  • Почему в Python при целочисленном делении (-1 // 2) получается ответ (-1)?

    aRegius
    @aRegius
    Python Enthusiast
    Добрый вечер.

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

    -1 / 2 = - 0.5. Ближайшее меньшее целое значение: -1.
    Ответ написан
    Комментировать
  • Как вывести значения словаря из списка обьектов сессии Питон/Джанго?

    Voskresenskyi
    @Voskresenskyi Автор вопроса
    Начинающий джанговод!
    Мой ответ таков:
    Вариант №1:
    views.py
    def add_product_to_cart(request):
    	if request.method == 'POST':
    		id = int(request.POST['product_id'])
    		if 'cart' not in request.session:
    			request.session['cart'] = []
    		request.session['cart'].append(int(id))
    		request.session.modified = True
    		return redirect("/")
    
    def show_cart(request):
    	cart = request.session.get('cart')
    	product_items = Product.objects.filter(id__in=cart) #можно и так Product.objects.filter(id__in=request.session['cart'])
    	content={
    		"product_items":product_items
    	}
    	return render (request, "orderdetail.html", content)

    Вариант №2 (в принципе отличия не серьезные):
    def add_product_to_cart(request):
    	if request.method == 'POST':
    		id = int(request.POST['product_id'])
    		price = int(request.POST['price'])
    		if 'cart' not in request.session:
    			request.session['cart'] = []
    		request.session['cart'].append(dict({'product_id': id, 'price': price}))
    		request.session.modified = True
    		return redirect("/")
    
    def show_cart(request):
    	cart = request.session.get('cart')
    	product_items = Product.objects.filter(id__in=(x['product_id'] for x in cart) )#можно прописать и для price вот только фактически это не нужно...
    	content={
    		"product_items":product_items
    	}
    	return render (request, "orderdetail.html", content)


    В добавок - читайте свой код! В данном случае я в темплейте пропустил(скорее всего нечаянно удалил) скобку))
    Спасибо iegor за помощь,)
    Ответ написан
    Комментировать