Django модульдік қолданбалы жүйені пайдаланады, бір қолданба бірнеше қолданбалардан тұрады, олардың әрқайсысы өз функцияларына жауап береді. Өздеріңіз байқағандай, мақаланы жазу кезінде сайтта «Білім қоры» бөлімі бар, онда мақалалар бөлінген бірнеше бөлімдер бар.
Алдыңғы Wordpress сайтында жұмыс істегенде, Qt оқулықтарының тізіміне жаңа мақалаларды қосу үшін уақыт босқа кетті. Сол сайтта бет автоматты түрде жасалады және жарияланған күйімен жаңа мақала сақталған кезде бұл мақала автоматты түрде сәйкес бөлімнің тізіміне қосылады.
Мен EVILEG COM мысалын қолдана отырып, мұның минималды нұсқада қалай жүзеге асырылатынын анықтауды ұсынамын.
Жоба құрылымы
Атап айтқанда, бұл сайт жобада екі қолданбаны пайдаланады:
- home - негізгі индекс бетіне, қате беттеріне және негізгі үлгілерге жауап беретін қолданба
- білім - мақалалар мен мақалалардың бөлімдеріне жауап беретін қосымша
Егер сіз егжей-тегжейлі қарасаңыз, жобаның құрылымы келесідей болады:
mysite/ manage.py mysite/ \_\_init\_\_.py settings.py urls.py wsgi.py home/ \_\_init\_\_.py admin.py apps.py models.py tests.py urls.py views.py templates/ home/ base.html knowledge/ \_\_init\_\_.py admin.py apps.py models.py tests.py urls.py views.py templates/ knowledge/ article.html index.html section.html
Жобаны және жобадағы қолданбаларды құру туралы бірнеше сөз. Pycharm әзірлеу ортасы пайдаланылды, ол жобаны негізгі модульдермен, соның ішінде әкімші панелімен дайындайды, сондықтан мен әдепкі бойынша қосылмаған нәрселер туралы айтатын боламын.
Қосымшаларды жасау үшін келесі пәрмендерді пайдалану керек:
python manage.py startapp home python manage.py startapp knowledge
settings.py параметрін орнату
Қолданбалы модульдер қолжетімді болуы үшін оларды жоба конфигурация файлына қосу керек.
INSTALLED\_APPS = [ 'home.apps.HomeConfig', 'accounts.apps.AccountsConfig', ... ]
Модельдер
Жобада екі үлгі түрі қолданылады:
- Бөлім – белгілі бір тақырыпқа жататын бір ортақ белгі бойынша барлық мақалаларды біріктіретін бөлімдер
- Мақал – мақалалардың өзі
Модельдер models.py файлында сипатталған
Бұл деректер үлгілерін әзірлеу үшін Django ішіне кіріктірілген Model. сыныбынан мұра пайдаланылды.Сонымен қатар, User пайдаланушы үлгісі пайдаланылды, өйткені мақалаларда тіркелген пайдаланушылар арасынан автор көрсетілген. сайтында.
from django.db import models from django.contrib.auth.models import User
Бөлім
Бөлім үлгісі мыналардан тұрады:
- Тақырып – бөлім тақырыбы
- URL – сайтта адрестің бір бөлігін қалыптастыру үшін пайдаланылады, яғни абсолютті жолдар сақталмайды, бірақ бөлімге баратын жолдың бір бөлігі.
- Сипаттама – мақалалар тізімінің алдында беттің жоғарғы жағында көрсетіледі
Модельдің кодта орындалуын қарастырайық:
class Section(models.Model): class Meta: db\_table = "section" section\_title = models.CharField(max\_length=200) section\_url = models.CharField(max\_length=50) section\_description = TextField() def \_\_str\_\_(self): return self.section\_title
Meta класы дерекқордағы кестелерге тікелей қатысты кейбір үлгі параметрлерін қайта анықтауға мүмкіндік береді. Бұл жағдайда кесте қалай шақырылатыны анықталады.
Модельде үш өріс бар, олардың екеуі CharField типті, ол енгізілген таңбалар саны шектеулі шағын жазбаларды білдіреді.
TextField түрі таңбалардың жеткілікті үлкен ерікті массивінің енгізілетінін білдіреді, оның ең үлкен өлшемі алдын ала белгісіз.
__str__ әдісін қайта анықтау және бұл жаңа әдіс емес, дәл басып шығару, әкімші панелінде көрсетілетін мақала тақырыбын қайтаруға мүмкіндік береді. Өйткені, егер бұл әдіс қайта белгіленбесе, онда әкімшідегі барлық жазбалар Бөлім нысаны сияқты көрінеді және бөлімдердің үлкен санымен қайда және не орналасқанын анықтау өте қиын болады.
Мақала
Модель келесі өрістерден тұрады:
- Мақаланың тақырыбы
- Бөлім – бұл Бөлімдер кестесінің сыртқы кілті, мақаланың белгілі бір бөлімге жататынын анықтайды.
- Автор – мақала авторы таңдайтын пайдаланушылар кестесінің сыртқы кілті
- Күні – жарияланған күні мен уақыты
- Мазмұн – бөлім үлгісіндегідей сипаттамаға ұқсас мәтіндік өріс
- Күй – мақалалар үшін бірнеше мәртебелерді қабылдаймын, қазіргі уақытта тек екеуі ғана пайдаланылады:
- Жоба – 0 мәні
- Жарияланған – 1 мәні
class Article(models.Model): class Meta: db\_table = "article" article\_title = models.CharField(max\_length=200) article\_section = models.ForeignKey(Section) article\_author = models.ForeignKey(User) article\_date = models.DateTimeField('Дата публикации') article\_content = TextField() article\_status = models.IntegerField() def \_\_str\_\_(self): return self.article\_title
Әкімші панелінде үлгілерді тіркеу
Әкімші панелінен мақалалар мен бөлімдерді өңдеу мүмкіндігін алу үшін оларды әкімші модулінде тіркеу қажет. Бұл сәйкес қолданбаның admin.py файлында орындалады.
from django.contrib import admin from .models import Section, Article admin.site.register(Section) admin.site.register(Article)
Көші-қон
Үлгілерді жаздыңыз, үлгілерде барлық қажетті өрістер бар екеніне сенімдісіз бе? Содан кейін дерекқорды тасымалдауды орындау керек. Ол үшін келесі пәрмендерді орындаңыз.
python manage.py makemigrations python manage.py migrate
Ескерту
Негізгі кілт әдетте автоматты түрде ауыстырылады және автоматты түрде өседі, сондықтан біз оны көрсетпейміз.
Үлгілер
Джангодағы шаблондар өте керемет, әсіресе оларды мұраға алуға болады және белгілі бір блоктар жойылады.
Жоба барлық басқа беттер мұраға алатын home қолданбасында бір негізгі үлгіні base.html жасады. Шартты үлгі құрылымы келесідей:
{% block head %} {% endblock %} {% block content %} {% block page %} {% endblock page %} {% block sidebar %} {% endblock %} {% endblock content %} {% block footer %} {% endblock %}
Бұл жағдайда басқа беттердегі үлгілерді мұраға алған кезде қайта анықталатын бес блок бар.
index.html
Бұл барлық бөлімдердің тізімі көрсетілетін қолданбаның негізгі бетіне арналған үлгі. extends операторын пайдалана отырып, біз нақты бетке арналған home. қолданбасының негізгі үлгісінен мұраға алатынымызды көрсетеміз.
Сіз байқаған боларсыз, Django үлгілеу тілі if, for, url. конструкцияларын пайдаланады, бірақ бөлім_list және бөлім айнымалылары қайдан келді? - бөлім_тізімі көріністе деректерді дайындау кезінде үлгіге мәтінмәндік мән ретінде беріледі. Бөлімдердің тізімі бар екенін тексергеннен кейін біз үлгіге қажетті мәндерді ауыстыра отырып, тізімнің барлық элементтерін аралаймыз. Бөлім Бөлім үлгісіне сәйкес болғандықтан, сәйкес үлгі өріс атаулары автоматты түрде таңдалады.
url мекенжайына келетін болсақ, бұл мәлімдеме бөлім атты білім қолданбасынан мекенжай үлгісін алу керектігін көрсетеді, сонымен қатар бұл мекенжай үлгісінде бір айнымалы бар екенін білеміз. бөлім нысанының url тағайындаңыз. Бұл үлгілер urls.py файлында сипатталған. Біз оларды сәл кейінірек қарастырамыз.
{% extends 'home/base.html' %} {% block page %} <article> <h1>Разделы</h1> {% if section\_list %} <ul> {% for section in section\_list %} <li> <a href="{% url 'knowledge:section' section.section\_url %}">{{ section.section\_title }}</a> </li> {% endfor %} </ul> {% endif %} </article> {% endblock %}
бөлімі.html
Бөлім үлгісінде осы бөлімге сәйкес келетін мақалалар тізімі қалыптастырылады. Бөлім айнымалысы үлгіге бөлім нысаны туралы ақпаратты қамтитын мәтінмән ретінде беріледі. Біз бөлімнің тақырыбын және оның сипаттамасын ауыстырамыз. Сипаттама пішімдеудің сақталғанын көрсететін қауіпсіз арнайы аргументімен ауыстырылғанын ескеріңіз. Бұл html белгілеуін сақтау үшін жасалуы керек, әйтпесе пайдаланушы әдемі жасалған сипаттаманың орнына html орналасу кодын көреді.
Сондай-ақ мұнда осы бөлімге жататын барлық мақалалар туралы ақпарат жинағы бар нұсқа бар және бұл бөлім.article_set.all деп қоңырау шалу арқылы жүзеге асырылады, яғни біз осы бөлімге сыртқы кілті бар барлық мақалаларды аламыз. Сұрыптау орындалатын параметрді көрсететін dictsort арқылы мақалаларды сұрыптаймыз.
Ал if блогы мақаланың күйін тексереді, яғни жарияланбаған мақалалар көрсетілмейді.
url, үшін мекенжай үлгісі қайтадан пайдаланылады, бірақ екі аргументпен.
{% extends 'home/base.html' %} {% block page %} <article> <h1>{{ section.section\_title }}</h1> <p>{{ section.section\_description|safe }}</p> <h2>Статьи</h2> <ul> {% for article in section.article\_set.all|dictsort:'article\_title' %} {% if article.article\_status %} <li> <a href="{% url 'knowledge:article' section.section\_url article.id %}"> {{ article.article\_title }} </a> </li> {% endif %} {% endfor %} </ul> </article> {% endblock %}
article.html
Көріп отырғаныңыздай, мақаланың үлгісі ол туралы бірдеңе қосу үшін жеткілікті нашар.
{% extends 'home/base.html' %} {% block page %} <article> <h1>{{ article.article\_title }}</h1> <p>{{ article.article\_content|safe }}</p> </article> {% endblock %}
Ескерту
Егер сіз жоба құрылымын қарасаңыз, қолданбалардың үлгілер қалталарында қолданбалармен бірдей атқа ие көбірек қалталар бар екенін және оларда бет үлгілері бар екенін көресіз. Бұл нақты қай үлгінің қолданылатынын анықтау үшін жасалады. Django барлық қалталардан үлгілерді іздейді және атқа сәйкес келетін бірінші үлгіні таңдайды. Ал егер атаулар қиылыса, мысалы, index.html, онда қате үлгі таңдалуы мүмкін. Сондықтан аттар кеңістігі қажетті үлгіні дәл анықтау үшін пайдаланылады.
Өнімділік
Бұл жағдайда көріністен жұмыс өте шектеулі, сондықтан мен бірден views.py. файлының толық тізімін беремін.
Біз View сыныбынан мұра аламыз және GET сұрауын, яғни пайдаланушының бет сұрауын орындауға жауап беретін get әдісін қайта анықтаймыз. Біз сондай-ақ үлгіні бізге қажет контексте өңдейтін render_to_response әдістерін және get_object_or_404 әдістерін импорттаймыз, ол нысан болса, автоматты түрде 404 қатесін қайтарады. табылмады, сәйкес айнымалыға сәйкес .
Аты бойынша сұрыпталған барлық бөлімдер EKnowledgeIndex ішіне қабылданады және section_list деген атпен контекстке орналастырылады, Бұл айнымалы index.html. шаблонында пайдаланылғаны есіңізде.
Арнайы Бөлім ESectionView ішіне сұралған URL мекенжайында жіберілетін аргумент арқылы қабылданады. kwargs urls.py файлында көрсетілген үлгіге сәйкес url мекенжайынан алынған айнымалылар үшін ғана жауап береді.
EAarticleView ішінде нәрселер әлдеқайда қызықты. Мәселе мынада, url үлгісі екі айнымалыны пайдаланады, бірақ мақаланы алу үшін id арқылы сұраныс жасау жеткілікті, яғни URL мекенжайына жіберілетін Негізгі кілт .
from django.views import View from django.shortcuts import render\_to\_response, get\_object\_or\_404 from .models import * class EKnowledgeIndex(View): template\_name = 'knowledge/index.html' def get(self, request, *args, **kwargs): context = {} context['section\_list'] = Section.objects.all().order\_by('section\_title') return render\_to\_response(template\_name=self.template\_name, context=context) class ESectionView(View): template\_name = 'knowledge/section.html' def get(self, request, *args, **kwargs): context = {} section = get\_object\_or\_404(Section, section\_url=self.kwargs['section']) context['section'] = section return render\_to\_response(template\_name=self.template\_name, context=context) class EArticleView(View): template\_name = 'knowledge/article.html' def get(self, request, *args, **kwargs): context = {} article = get\_object\_or\_404(Article, id=self.kwargs['article\_id']) context['article'] = article return render\_to\_response(template\_name=self.template\_name, context=context)
URL үлгісі
Жарайды, бәрі жазылуы керек, бірақ оның жұмыс істеуіне, атап айтқанда сұраулар өңделетін url үлгілерін орнатуға өте аз қалды.
Django ерекшелігі - бұл үлгілер үлгі контроллерлерінен алынбаған тұрақты өрнек тексерулері болып табылады. Жеке мен үшін бұл тәсіл анық және ашық болып шықты, маған ұнайды. Ендеше, парақтарымызды қалай жандандыруға болатынын көрейік.
менің сайтым/менің сайтым/urls.py
Алдымен mysite/mysite/urls.py файлында үлгілерді орнату керек, ол сұрауды қай қолданбаға жіберу керектігін анықтайды. Мұнда сіз үйге, қолданбасына бағыт бар екенін көре аласыз, сайттың негізгі беті сонда көрсетіледі, бірақ мен бұл бөліктің сипаттамасына тоқталмаймын, өйткені біз бұл туралы айтпаймыз. мақала. Сондай-ақ сайттың басқару панеліне және бөлімдер мен мақалаларға жауап беретін білім, қосымшасына бағыт бар.
қосады, home және knowledge. қолданбаларында urls.py файлдарын қамтиды.
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^', include('home.urls')), url(r'^knowledge/', include('knowledge.urls')), url(r'^admin/', admin.site.urls), ]
менің сайтым/knowledge/urls.py
app_name үлгілердегі аттар кеңістігіне жауапты. Есіңізде ме? Үлгіде сәл жоғарырақ 'білім:бөлім' жазбасы болды.
Нені және қайда жіберілетінін тұрақты адамдар анықтайды. Жазбаларға қатысты
Және
Ал, name шаблонның URL мекенжайының атын, яғни 'білім:бөліміндегі' екінші бөлікті көрсетеді.
Ал, мен соңғы атап өткім келетін нәрсе - шаблонда бар ^ символы. Оның көмегімен үлгінің бұрыннан танылған бөлігі жойылады. Яғни, бұл URL мекенжайларының басында mysite/mysite/urls.py. ішінде бұрын танылған knowledge/ , бар.
from django.conf.urls import url from . import views app\_name = 'knowledge' urlpatterns = [ url(r'^$', views.EKnowledgeIndex.as\_view(), name='index'), url(r'^(?P<section>[\w]+)/$', views.ESectionView.as\_view(), name='section'), url(r'^(?P<section>[\w]+)/(?P<article\_id>[0-9]+)/$', views.EArticleView.as\_view(), name='article') ]
Django үшін Timeweb хостының VDS сервері ұсынамын.
Спасибо за ваши статьи. Очень понятно и качественно пишите. Есть пара моментов в данной статье, которые мне кажутся спорными. Например, именование полей внутри моделей(article_title, article_date вместо просто title и date). Думаю добавлять в качестве префикса имя модели несколько избыточно - поля без модели не используются и без всяких префиксов всегда понятно откуда они. Второй момент это использование в шаблоне для ссылки на конкретный объект тег url. Гораздо удобнее реализовать для модели метод get_absolute_url и использовать его. Это даст возможность полностью менять схему урлов без поиска и переписывания всех шаблонов. К тому же этот метод используется стандартной админкой для формирования ссылок "посмотреть на сайте". Ну и ваши представления легче было наследовать от соответсвующих generic views - DetailView, ListView.
Хотя может это всё допущения чтобы не усложнять материал.
Спасибо за отзыв.
Хотелось спросить, можно ли создать многоуровневые url из свойств модели? Я вот с часик лежал, искал как это сделать не нашел, вопрос на хабре оставил, никто не ответил. Оригинальная документация говорит только об одном слаге, а все примеры заканчиваются на том, что есть домен и к нему slug. Я просто хотел прикрепить запись к определенной категории, и еще одной субкатегории, т.е типо домен/категория/подкатегории/запись
я сделал подобное, но блин, доступ к записи осуществляется даже с др.категории и вообще с любимым текстом, т.е ссылка каноническая, могу перейти и по test/test/запись и по nowork/test/запись, передавал в модель свойства вот так: kwargs=("url":self.url, "cat":self.cat.url, "sub":self.sub.url)
Если я правильно понимаю ваш вопрос, то нечто подобное у меня реализовано для страниц правил пользования сайтом, вот например страница тем форума
Но там я формирую полный путь, укладываю его в slug, а вот url шаблон у меня сделан так
Но у меня реализация там сделана за счёт того, что я задаю частичный url, который собирает все parent страницы формирует уже итоговый url и кладёт его куда надо.
Ещё делал раньше как вы делаете, но я так полагаю, что у вас код смотреть нужно, наверняка у вас неправильно написан код где-то:
К слову говоря, если делали по этой статье, то там тоже в EArticleView нужно ещё добавить проверку на slug раздела, и если не совпадаетЮ, то выкинуть ошибку 404. Так что да, косяк в статье.
Я делаю вот так у себя в модели для получения ссылки:
Там где доработать это я закомментил, ибо получалось доступность по всем категориям, потом выяснил, что так вообще по всей ссылки.
models.py
Вьюшка:
URLs
Запись доступна по articles/blog/название статьи, но таким же образом она доступна к неподвязанной категории, т.е articles/files/название статьи
Также можно любой текст можно подставить, articles/131411414/название статьи и будет тоже доступно.
Ну я так и думал. Здесь нужно или обычный View использовать, или формировать slug так, чтобы он содержал slug категории, и как у меня использовать path, но тут тогда будет проблем в том, что тогда url категории скорее всего перестанет работать.
Так что или берите обычный View, добавляйте туда метод get, и проверяйте как slug статьи, так и slug категории, которая будет привязана к статье, либо переопределяйте метод get_object у DetailView, но там также нужно будет ковырять как slug статьи, так и slug категории
Хорошо, посмотрю что получится с простым View
Отлично. Спасибо. Вопрос, как мне теперь передать на индексную страницу(ту которая по умолчанию) содержание только статей, без секций? И вообще передать на дефолтную страницу? Что то не получается. PS: в джанго - недавно, неделю.
Я дура. Разобралась. Но, остаюсь вашим читателем)