Django vs PHP

в разделе Программирование | Метки: Django, Python, PHP

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

Я поискал несколько уже готовых скриптов для создания каталогов, в том числе и платных и взломанных, все было не тем что мне нужно было. Мне хотелось такой же каталог как Яндекс.Каталог или что-то подобное. Для хранения в базе данных древовидной структуры каталога я взял идею из этой презентации. В общем я написал класс для работы с таким каталогом. Потом меня это быстро все достало, мало того что надо было написать только этот класс, надо было еще написать админку. Кроме всего этого каталог был лишь частью того что мне хотелось создать на этом сайте.

Решил попробовать Drupal, там уже вроде было все что мне надо, в том числе и каталог, завязанный на taxonomy. Не помню чем, но он меня не устроил, хотя я и переписал его под себя как хотелось.

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

CREATE TABLE `directory_russia` ( 
  `id` INT(11) NOT NULL AUTO_INCREMENT, 
  `parent_id` INT(11) NOT NULL, 
  `path_string` VARCHAR(255) NOT NULL, 
  `name` VARCHAR(255) NOT NULL, 
  `depth` INT(11) NOT NULL, 
  `region_id` INT(11) NOT NULL, 
  PRIMARY KEY  (`id`), 
  KEY `directory_russia_region_id` (`region_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 

models.py в Django

class Russia(models.Model): 
    parent_id = models.IntegerField() 
    path_string = models.CharField(maxlength=255) 
    name = models.CharField(maxlength=255) 
    depth = models.IntegerField() 
    region = models.ForeignKey(Region) 
    def __unicode__(self): 
        return self.name 
    class Admin: 
        pass 

в views.py я написал только одну фукнцию которая строит путь от корня каталога, до текущего раздела:
def build_node_path(path): 
  node_path = [] 
  for node_id in path.rsplit('/'): 
    node_object = Russia.objects.get(pk=node_id) 
    node_path.append(<a href='/cat/' + str(node_object.id) + '/>' + node_object.name + '</a>') 
  return " > ".join(node_path) 

в итоге получается путь типа "Раздел-1 > подраздел-1 > подраздел-2"
сами данные для каталога хранятся в другой таблице
class Org(models.Model): 
  directory = models.ManyToManyField(Russia) 
  name = models.CharField(maxlength=255) 
  description = models.TextField() 
  directory_order = models.IntegerField(default=2) 
  updated = models.DateTimeField(auto_now=True) 
  def __unicode__(self): 
      return self.name 
  class Admin: 
    pass

я немного изменил способ хранения, и путь храню примерно так 2/3/4 (то есть в начале и в конце нет /, в отличии примера с talks.php.net). В итоге по функциональности получается каталог точно такой же как у Яндекса, пока я застрял на постраничном выводе, он работает но не так как бы хотелось :)

Поле ManyToManyField позволяет хранить в разных разделах один и тот же элемент, примерно так же как если в яндекс каталоге зайти в Hi-tech там будут все элементы из всех подразделов.

ps: полезная настройка в settings.py которая устанавливает что все MySQL таблицы по умолчанию будут InnoDB

DATABASE_OPTIONS = {"init_command": "SET storage_engine=INNODB",}

если это не указать, то таблицы будут MyISAM и ForeignKeys создаваться не будут.