Jump to content
  • 0

Выбор серверного языка


DivMan
 Share

Question

Recommended Posts

  • 0
Если хорошо знать JS, то, что лучше учить NodeJS или PHP?

 

Node.js это не язык программирования.

 

Твой вопрос сейчас звучит как: "Если у меня есть права категории В, то что лучше взять Audi или сдать еще на категорию С?"

Link to comment
Share on other sites

  • 0

=)

 

Вопрос скорее про стек технологий. И тут зависит от многих вещей. Если знаешь javascript это ещё не значит что будет легче осваивать программирование для бекенда, нужно понимать что и как работает на сервере, базы данных и т.д. И вот тут на мой вгляд вообще в принципе нет разницы какой стек выбрать. Выбирайте тот который лично вам больше нравится.

Link to comment
Share on other sites

  • 0

Что будет делать фронтэндщик с нодом - непонятно мне.

 

Забавно. Мы уже крепко используем ноду в повседневной работе, но при этом говорим «непонятно, зачем оно» :)

Ведь grunt|gulp — это нодовые приложения в сущности. babel тоже. Dev-сервер же вы наверное тоже express или connect используете :)

Link to comment
Share on other sites

  • 0

Но это же не означает, что нужно знать саму ноду. Зачем мне подробности ноды если grunt поставил и он пашет себе?

Это тоже самое если чтобы использовать windows надо знать c/c++ assembler и так далее.

Edited by Нарек
Link to comment
Share on other sites

  • 0
Ведь grunt|gulp — это нодовые приложения в сущности. babel тоже. Dev-сервер же вы наверное тоже express или connect используете

вы работаете всего лишь с инструментами, написанными на нем) 

Ведь grunt|gulp

приложения приложений  :)

Link to comment
Share on other sites

  • 0

так-то оно так, но подвох в том, что нода подкралась столь хитро, что используем её и даже не задумываемся о том, что это происходит.

А где дев-сервер для разработки фронтэнда, там волей-неволей закрадывается крамольная мысль, что может и никакой nginx даром не нужен и на боевом сервере. А порой сделаешь что-нибудь на сокетах, и таковая крамольная мысль так и вовсе уверенно себя чувствует :)

Я всего лишь о том, что нода неизбежна, и никуда от неё, родимой, не деться.

Link to comment
Share on other sites

  • 0

 

Python 

 

Он востребован? 

 

Каждый второй проект на питоне, если точнее, то на Django. Но дело даже не в востребованности. Востребованность будет, если предлагаете услуги достойного уровня. Недавно на моих глазах человеку удалось найти работу с программированием на фортране :)

Если себя любите, то обратите внимание на Python: это самый красивый, лаконичный и выразительный язык.

Link to comment
Share on other sites

  • 0

Ух ты ж тайком всех пхпшников и остальных обозвал, не любят они себя, правильно :-D

Прям лозунг для партии:-)

Лозунги оставим политикам :-)

А по существу ведь могу обосновать. Не знаю, позволяет ли формат форума? Я тут новичок, правила правилами, а традиций не знаю. Мэтры дадут добро — прямо с примерами кода могу, как делаются некоторые вещи на php, ruby, js, coffeescript и python — это языки, на которых пишу по работе, другие не имею возможности сравнивать. Сегодня выходной, почему бы и не побаловаться таким :-)

Link to comment
Share on other sites

  • 0
Лозунги оставим политикам
будь моя воля - собрал бы их всех со всех стран и вывез на необитаемый остров - пусть там лозунгами меряются, нормальных людей не отвлекают

 

 

прямо с примерами кода могу, как делаются некоторые вещи на php, ruby, js, coffeescript и python

вот это интересно. ) на питоне и RoR что нибудь необычное запили....     эта тема здесь не развита.  Мне больше нравится не в интернете искать, а парочку хороших скриптов просмотреть, чтобы сразу понять плюсы и минусы языка. не я один такой , maybe =)
  • Like 1
Link to comment
Share on other sites

  • 0

что нибудь необычное запили....

 

есть пожелания?

Откровенно говоря, необычное пишу редко.

Просто сейчас проект на YII2, где простые вещи делаются сложно, само собой в процессе работы получается сравнивать с любимыми Python/Django, отнюдь не в пользу как php, так и YII2, так и прочих фреймворков, вдохновлённых рельсами.

Link to comment
Share on other sites

  • 0

Посмотрел на код python, похоже на плагиат JS

 

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

 

Ну вот например, прямо из текущего проекта (просто что прямо под рукой оказалось):

class VacancyList extends ItemList {    get matchingQuery() {        let qs = this._location.query,            matched = super.matchingQuery;        if ('salary' in qs){            let salary = parseInt(qs['salary']);            if (!isNaN(salary) && salary > 0) {                matched = matched.filter((d)=>                    parseInt(d.salary) >= qs['salary']                );            }        }        return(matched);    }}

Как то же самое было бы на питоне:

class VacancyList(ItemList):    def getMatchingQuery(self):        matched = super().getMatchingQuery()        try:            salary = self._location.query.qs.salary            if salary > 0:                return [                    d for d in matched                     if d.salary >= self._location.query.qs.salary                ]        except (AttributeError, TypeError):            pass        return matched
Link to comment
Share on other sites

  • 0

вот это интересно. ) на питоне и RoR что нибудь необычное запили....     эта тема здесь не развита.

 

 

 

Не, давайте обычное. Самое обычное, обычнее некуда.

Просто пишу сейчас, впечатляюсь, аж волосы дыбом стают (а они у меня по пояс длинные, их надо суметь так поднять).

И на YII2(php) vs Django(python). Про RoR можно додумать, YII с него писался. Только язык Ruby попроще, чем php.

 

Задача: лента новостей. Самая обычная лента новостей. Список и детальная страница каждой отдельной новости. У каждой новости есть заголовок, картинка, дата, основной текст, анонс. Адреса: /news/ для списка, /news/1/ для детальной. Основной текст и анонс могу произвольно оформляться html/css. В админке для этого визуальный редактор. Все поля обязательны, кроме анонса, если анонс не задан, он формируется из первых 20 слов основного текста, но так, чтобы все открытые тэги оказались закрыты.

Лента новостей на двух языках: русском и английском. В админке переключаемся по вкладкам, пишем в варианты полей для каждого из языков свой текст. В публичной части адрес предваряется префиксом /ru/ или /en/, и в зависимости от этого выбираем тексты на нужном языке.

 

Казалось бы, очень простая задача, наитипичнейшая.

 

Модель на YII2 (php):

<?php/** * Created by PhpStorm. * User: abrahadabra * Date: 22.12.15 * Time: 12:42 */namespace app\models;use Yii;use yii\db\ActiveRecord;use yii\helpers\StringHelper;use yii\web\UploadedFile;/** * This is the model class for table "news". * * @property integer $id * @property string $date * @property string $name * @property string $name_ru * @property string $name_en * @property string $announce * @property string $announce_ru * @property string $announce_en * @property string $text * @property string $text_ru * @property string $text_en * @property string $image * @property string $filename *//** * @var UploadedFile image attribute */class News extends ActiveRecord{    public $image;    public $del_img;    /**     * @inheritdoc     */    public static function tableName()    {        return 'news';    }    /**     * @inheritdoc     */    public function rules()    {        return [            [['date', 'name_ru', 'name_en', 'text_ru', 'text_en'], 'required'],            [['date', 'image'], 'safe'],            [['image'], 'image',  'extensions' => 'png,jpg,jpeg', 'skipOnEmpty' => true],            [['del_img'], 'boolean'],            [['name', 'name_ru', 'name_en'], 'string', 'max' => 256],            [['announce', 'announce_ru', 'announce_en'], 'string', 'max' => 2048],            [['text', 'text_ru', 'text_en'], 'string', 'max' => 65535],        ];    }    /**     * @return \yii\db\ActiveQuery     */    public function getLanguage()    {        return $this->hasOne(Language::className(), ['id' => 'language_id']);    }    public function upload()    {        if ($this->validate()) {            $this->image->saveAs('news/' . $this->image->baseName . '.' . $this->image->extension);            $this->image = $this->image->baseName . '.' . $this->image->extension;            return true;        } else {            return false;        }    }    public function getImageUrl()    {        if ($this->filename) {            return "/news/".$this->filename;        } else {            return "";        }    }    public function getThumbUrl()    {        if ($this->filename) {            return "/news/thumbs/".$this->filename;        } else {            return "";        }    }    /**     * @inheritdoc     */    public function attributeLabels()    {        return [            'id' => 'ID',            'date' => Yii::t('app', 'Дата'),            'filename' => Yii::t('app', 'Картинка'),            'image' => Yii::t('app', 'Загрузить картинку'),            'del_img' => Yii::t('app', 'Удалить картинку'),            'name' => Yii::t('app', 'Заголовок'),            'name_ru' => Yii::t('app', 'Заголовок'),            'name_en' => Yii::t('app', 'Заголовок'),            'announce' => Yii::t('app', 'Анонс'),            'announce_ru' => Yii::t('app', 'Анонс'),            'announce_en' => Yii::t('app', 'Анонс'),            'text' => Yii::t('app', 'Текст'),            'text_ru' => Yii::t('app', 'Текст'),            'text_en' => Yii::t('app', 'Текст'),        ];    }    public function getName()    {        $lang = Language::getCurrent();        return trim($this->getAttribute("name_".$lang->alias));    }    public function getAnnounce($strict=false)    {        $lang = Language::getCurrent();        $announce = trim($this->getAttribute("announce_".$lang->alias));        if ($strict || strlen($announce) > 0) {            return $announce;        } else {            return StringHelper::truncateWords($this->getText(), 20, '…');        }    }    public function getText()    {        $lang = Language::getCurrent();        return trim($this->getAttribute("text_".$lang->alias));    }}

Ещё нужна модель языка, но я её приводить не буду, а то и так слишком много кода.

 

Для той же задачи модель на Django (Python):

from django.db import modelsfrom django.utils.translation import ugettext_lazy as _from ckeditor.fields import RichTextFieldclass News(models.Model):    name = models.CharField(_('title'), max_length=256)    date = models.DateField(_('date'), default=timezone.now)    image = models.ImageField(_('image'), upload_to='news', null=True, blank=True)    announce = RichTextField(_('announce'), config_name="announce", max_length=2048, null=True, blank=True)    text = RichTextField(_('text'))    def get_absolute_url(self):        return reverse('news', args=[str(self.pk)])    def __str__(self):        return self.name    class Meta:        ordering = ['-date']        verbose_name = _('article')        verbose_name_plural = _('news')

Здесь первое, на что можно обратить внимание — количество кода. Второе — его осмысленность.

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

В случае Django чётко видна структура модели. Перечислены все поля, для каждого поля его тип, подпись, валидация, значения по умолчанию. Для картинки, как и ожидается, одно поле, все типовые действия над которым реализованы в соответствующем классе. В классе модели же методы для вычисления адреса страницы объекта и строкового представления (что необязательно, но в ряде случаев удобно). Там же сортировка по умолчанию.

Для Django нужна ещё регистрация модели как переводимой:

from modeltranslation.translator import translator, TranslationOptionsfrom news.models import Newsclass NewsTranslationOptions(TranslationOptions):    fields = ('name', 'announce', 'text')translator.register(News, NewsTranslationOptions)

 

 

Теперь это добро надо вывести в админку.

Не буду приводить весь код для YII2. Вот только контроллер:

<?php/** * Created by PhpStorm. * User: abrahadabra * Date: 22.12.15 * Time: 13:14 */namespace app\modules\dashboard\controllers;use Yii;use app\models\News;use yii\data\ActiveDataProvider;use yii\web\Controller;use yii\web\NotFoundHttpException;use yii\filters\VerbFilter;use yii\web\UploadedFile;use yii\imagine\Image;class NewsController extends Controller{    public $defaultAction = 'index';    public function behaviors()    {        return [            'verbs' => [                'class' => VerbFilter::className(),                'actions' => [                    'delete' => ['post'],                ],            ],        ];    }    /**     * Lists all News models.     * @return mixed     */    public function actionIndex()    {        $dataProvider = new ActiveDataProvider([            'query' => News::find(),        ]);        return $this->render('index', [            'dataProvider' => $dataProvider,        ]);    }    /**     * Displays a single News model.     * @param integer $id     * @return mixed     */    public function actionView($id)    {        return $this->render('view', [            'model' => $this->findModel($id),        ]);    }    /**     * Creates a new News model.     * If creation is successful, the browser will be redirected to the 'view' page.     * @return mixed     */    public function actionCreate()    {        $model = new News();        if ($model->load(Yii::$app->request->post()) && $model->save()) {            $this->uploadImage($model, "news/");            return $this->redirect(['view', 'id' => $model->id]);        } else {            return $this->render('create', [                'model' => $model,            ]);        }    }    protected function createDirectory($path) {        if (!file_exists($path)) {            mkdir($path, 0775, true);        }    }    protected function uploadImage($model, $imagePath)    {        $file = UploadedFile::getInstance($model, 'image');        if($model->del_img)        {            if(file_exists(Yii::getAlias('@webroot'.$model->getImageUrl())))            {                unlink(Yii::getAlias('@webroot'.$model->getImageUrl()));                $model->filename = '';                $model->save();            }        }        if ($file && $file->tempName) {            $fileName = $file->baseName . '.' . $file->extension;            $this->createDirectory($imagePath);            $file->saveAs($imagePath . $fileName);            $this->createDirectory($imagePath . "thumbs/");            Image::thumbnail($imagePath . $fileName, 180, 115)->save($imagePath . "thumbs/" . $fileName, ['quality' => 80]);            $model->filename = $fileName;            $model->save();        }    }    /**     * Updates an existing News model.     * If update is successful, the browser will be redirected to the 'view' page.     * @param integer $id     * @return mixed     */    public function actionUpdate($id)    {        $model = $this->findModel($id);        if ($model->load(Yii::$app->request->post()) && $model->save()) {            $this->uploadImage($model, "news/");            return $this->redirect(['view', 'id' => $model->id]);        } else {            return $this->render('update', [                'model' => $model,            ]);        }    }    /**     * Deletes an existing News model.     * If deletion is successful, the browser will be redirected to the 'index' page.     * @param integer $id     * @return mixed     */    public function actionDelete($id)    {        $this->findModel($id)->delete();        return $this->redirect(['index']);    }    /**     * Finds the News model based on its primary key value.     * If the model is not found, a 404 HTTP exception will be thrown.     * @param integer $id     * @return News the loaded model     * @throws NotFoundHttpException if the model cannot be found     */    protected function findModel($id)    {        if (($model = News::findOne($id)) !== null) {            return $model;        } else {            throw new NotFoundHttpException('The requested material does not exist.');        }    }}

Обратим внимание на экшны этого контроллера, на эту тучу кода для типовых-типовых задач. А ещё обратим внимание на метод загрузки картинки. Вручную загружаем, проверяем существование каталога и т.д. и т.п. Сразу поясню, что это способ, рекомендованный официальной документацией.

Но контроллера мало. Нужно вывести страницы. Список:

<?phpuse yii\helpers\Html;use yii\grid\GridView;/* @var $this yii\web\View *//* @var $dataProvider yii\data\ActiveDataProvider */$this->title = Yii::t('app', 'Новости');$this->params['breadcrumbs'][] = $this->title;?><div class="news-index">    <h1><?= Html::encode($this->title) ?></h1>    <p>        <?= Html::a('Create News', ['create'], ['class' => 'btn btn-success']) ?>    </p>    <?= GridView::widget([        'dataProvider' => $dataProvider,        'columns' => [            ['class' => 'yii\grid\SerialColumn'],            'id',            [                'label' => Yii::t('app', 'Заголовок'),                'format' => 'html',                'content' => function($data){                    return $data->getName();                },            ],            ['class' => 'yii\grid\ActionColumn'],        ],    ]); ?></div>

Форма добавления/редактирования:

<?phpuse yii\helpers\Html;use yii\helpers\Url;use yii\widgets\ActiveForm;use vova07\imperavi\Widget;use yii\jui\DatePicker;/* @var $this yii\web\View *//* @var $model app\models\News *//* @var $form yii\widgets\ActiveForm */$thumbUrl = $model->getThumbUrl();$imageUrl = $model->getImageUrl();?><div class="news-form">    <?php $form = ActiveForm::begin([        'options' => ['enctype'=>'multipart/form-data']    ]); ?>    <div class="row">        <div class="col-md-6">            <?= $form->field($model, 'date')->widget(\yii\jui\DatePicker::classname(), [                'dateFormat' => 'yyyy-MM-dd',            ]) ?>        </div>        <div class="col-md-6">            <?php if($thumbUrl && $imageUrl): ?>                <a href="<?= $imageUrl ?>" class="fancybox">            <?= Html::img($thumbUrl, ['class'=>'img-responsive']) ?>                </a>            <?= $form->field($model,'del_img')->checkBox() ?>            <?php endif ?>            <?= $form->field($model, 'image')->fileInput() ?>        </div>    </div>    <div class="row">        <div class="col-md-12">            <ul class="nav nav-tabs" role="tablist">                <li role="presentation" class="active"><a href="#ru" aria-controls="home" role="tab" data-toggle="tab">Русский</a></li>                <li role="presentation"><a href="#en" aria-controls="home" role="tab" data-toggle="tab">English</a></li>            </ul>            <div class="tab-content">                <div role="tabpanel" class="tab-pane active" id="ru">                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'name_ru')->textInput(['maxlength' => true]) ?>                        </div>                    </div>                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'announce_ru')->widget(Widget::className(), [                                'settings' => [                                    'lang' => 'ru',                                    'minHeight' => 100,                                    'buttons' => [                                        'format',                                        'bold',                                        'italic',                                        'deleted',                                        'lists',                                        'link',                                    ],                                    'buttonSource' => true,                                    'plugins' => [                                        'clips',                                        'fullscreen',                                    ]                                ]                            ]) ?>                        </div>                    </div>                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'text_ru')->widget(Widget::className(), [                                'settings' => [                                    'lang' => 'ru',                                    'minHeight' => 200,                                    'buttonSource' => true,                                    'plugins' => [                                        'table',                                        'clips',                                        'fullscreen',                                        'imagemanager',                                        'filemanager'                                    ],                                    'formatting' => ['p', 'blockquote', 'h2'],                                    'imageUpload' => Url::to(['/site/image-upload']),                                    'imageManagerJson' => Url::to(['/site/images-get']),                                    'fileManagerJson' => Url::to(['/site/files-get']),                                    'fileUpload' => Url::to(['/site/file-upload'])                                ]                            ]) ?>                        </div>                    </div>                </div>                <div role="tabpanel" class="tab-pane" id="en">                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'name_en')->textInput(['maxlength' => true]) ?>                        </div>                    </div>                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'announce_en')->widget(Widget::className(), [                                'settings' => [                                    'lang' => 'ru',                                    'minHeight' => 100,                                    'buttons' => [                                        'format',                                        'bold',                                        'italic',                                        'deleted',                                        'lists',                                        'link',                                    ],                                    'buttonSource' => true,                                    'plugins' => [                                        'clips',                                        'fullscreen',                                    ]                                ]                            ]) ?>                        </div>                    </div>                    <div class="row">                        <div class="col-md-12">                            <?= $form->field($model, 'text_en')->widget(Widget::className(), [                                'settings' => [                                    'lang' => 'ru',                                    'minHeight' => 200,                                    'buttonSource' => true,                                    'plugins' => [                                        'table',                                        'clips',                                        'fullscreen',                                        'imagemanager',                                        'filemanager'                                    ],                                    'formatting' => ['p', 'blockquote', 'h2'],                                    'imageUpload' => Url::to(['/site/image-upload']),                                    'imageManagerJson' => Url::to(['/site/images-get']),                                    'fileManagerJson' => Url::to(['/site/files-get']),                                    'fileUpload' => Url::to(['/site/file-upload'])                                ]                            ]) ?>                        </div>                    </div>                </div>            </div>        </div>    </div>    <div class="form-group">        <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>    </div>    <?php ActiveForm::end(); ?></div>

Всё не буду приводить. А нужно ещё несколько вьюх, а затем в базовый шаблон админки поставить ссылку на этот раздел.

 

А для Django приведу весь код:

from django.contrib import adminfrom modeltranslation.admin import TranslationAdminfrom .models import Articleclass ArticleAdmin(TranslationAdmin):    list_display = ['name', 'date']admin.site.register(Article, ArticleAdmin)

Это всё.

То есть, конечно, можно делать мудрёные специфичные формы, если в этом есть необходимость, но даже самая мудрёная будет нагляднее и проще, в характерном декларативном стиле. В большинстве же случаев такой необходимости нет, и можно ограничиться крохотным классом. В админке будет список, формы добавления/редактирования, возможность удаления. Также легко в одну строчку можно наладить поиск или фильтр. И всё это будет красиво и удобно выглядеть.

 

Во внешней части.

Контроллер на YII2.

<?php/** * Created by PhpStorm. * User: abrahadabra * Date: 22.12.15 * Time: 13:36 */namespace app\controllers;use Yii;use yii\data\Pagination;use yii\web\Controller;use app\models\News;use app\models\Page;use app\models\Language;use yii\web\NotFoundHttpException;class NewsController extends Controller{    public function actionIndex()    {        $query = News::find();        $countQuery = clone $query;        $pages = new Pagination([            'totalCount' => $countQuery->count()        ]);        $pages->setPageSize(10);        $reviews = $query->offset($pages->offset)->limit($pages->limit)->all();        return $this->render('index', [            'model' => new News(),            'news' => $reviews,            'page' => $this->getPage(),            'pages' => $pages        ]);    }    public function actionView($id)    {        $model = News::findOne($id);        if ($model === null) {            throw new NotFoundHttpException;        }        $page = $this->getPage();        $path = $page->getPath(True);        $path[] = $model->getName();        return $this->render('view', [            'article' => $model,            'page' => $page,            'path' => $path        ]);    }    protected function getPage()    {        $lang = Language::getCurrent();        return Page::findOne([            'alias' => 'news',            'language_id' => $lang->id        ]);    }}

View на Django

(в архитектуре django view — это вроде аналога контроллера в классическом MVC)

from django.views.generic import ListView, DetailViewfrom .models import Newsclass NewsListView(ListView):    model = News    template_name = 'news/list.html'    context_object_name = 'news'    paginate_by = 10class NewsDetailView(DetailView):    model = News    template_name = 'news/detail.html'    context_object_name = 'article'

Опять же: объём кода и его понятность.

 

Ну и шаблоны.

Шаблон списка на YII2:

<?php/** * Created by PhpStorm. * User: abrahadabra * Date: 22.12.15 * Time: 13:40 */use yii\helpers\Url;use app\widgets\CustomPagerWidget;/** @var $news \yii\db\ActiveRecord */$this->title = $page->meta_title;$this->registerMetaTag(['name' => 'description', 'content' => $page->meta_description]);$this->registerMetaTag(['name' => 'keywords', 'content' => $page->meta_keywords]);$this->params['breadcrumbs'] = $page->getPath();?><div class="container"><div class="row"><div class="col-md-12"><div class="border-page-header">    <h1 class="pull-left"><?= Yii::t('app', 'Новости') ?></h1>    <div class="pull-right">        <?= CustomPagerWidget::widget(['pagination' => $pages]) ?>    </div></div></div></div><div class="row"><div class="col-md-12"><ul class="media-list news_list index_content_list"><?php foreach($news as $article): ?>    <li class="media news_item index_content_list_item">        <div class="media-left"><?php$thumbUrl = $article->getThumbUrl();$imageUrl = $article->getImageUrl();?><?php if($thumbUrl && $imageUrl): ?>            <a href="<?= $imageUrl ?>" class="fancybox">                <img src="<?= $thumbUrl ?>" class="media-object">            </a><?php endif ?>        </div>        <div class="media-body">            <?php $date = new DateTime($article->date); ?>            <div class="news-date"><?= $date->format('j.m.Y') ?></div>            <h2 class="media-heading"><?= $article->getName() ?></h2>            <div class="news-text"><?= $article->getAnnounce() ?></div>            <a href="<?= Url::toRoute(['news/view', 'id' => $article->id]) ?>" class="btn btn-default"><?= Yii::t('app', 'читать далее') ?></a>        </div>    </li><?php endforeach ?></ul></div><div class="col-md-12">    <hr class="p_media">    <div class="pull-right">        <?= CustomPagerWidget::widget(['pagination' => $pages]) ?>    </div></div></div></div>

 

Шаблон списка на Django:

{% load i18n pagination thumbnail %}{% block content %} <div class="container"><div class="row"><div class="col-md-12"><div class="border-page-header">    <h1 class="pull-left">{% trans('News') %}</h1>    <div class="pull-right">        {% pagination %}    </div></div></div></div><div class="row"><div class="col-md-12"><ul class="media-list news_list index_content_list">{% for article in news %}    <li class="media news_item index_content_list_item">        <div class="media-left">            {% thumbnail article.image "120x120" crop="center" as im %}            <a href="{{ article.get_absolute_url }}"><img src="{{ im.url }}" class="media-object"></a>            {% endthumbnail %}        </div>        <div class="media-body">            <div class="news-date">{{ article.date|date('j.M.Y') }}</div>            <h2 class="media-heading">{{ article.name }}</h2>            <div class="news-text">{{ article.announce|default:article.text|truncatewords_html:20 }}</div>            <a href="{{ article.get_absolute_url }}" class="btn btn-default">{% trans "Read more" %}</a>        </div>    </li>{% endfor %}</ul></div><div class="col-md-12">    <hr class="p_media">    <div class="pull-right">        {% pagination %}    </div></div></div></div>{% endblock %}

Здесь всё более или менее похоже, но смотрим на наличие программной логики в шаблонах. Отличия в шаблонах детальных страниц примерно такого же плана, не буду повторяться.

 

Вот такое сравнение языков и фреймворков на простейшей типовой задаче.

 

 

Если хорошо знать JS, то, что лучше учить NodeJS или PHP?

Python

 

Предлагаю согласиться.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy