- 1. Project structure
- 2. Configuration the settings.py
- 3. Model
- 4. Templates
- 1. index.html
- 2. section.html
- 3. article.html
- 4. Note
- 5. View
- 6. URL templates
In Django uses a modular system of applications, where one application is composed of several applications, each responsible for its functionality. As you have noticed, at the time of this writing, the site has a section "Knowledge", in which there are several sections, which have divided the article.
When working with the previous site on Wordpress, mindlessly spend time on the addition of new articles to the list of lessons on Qt. On this same site the page is automatically generated and save a new article is published with the status, this article will automatically enters the relevant section of the list.
I suggest to understand how it is implemented in a minimal version of the example EVILEG COM.
Project structure
Specifically, this website uses two applications in the project:
- home - an application that is responsible for the main index page, error pages and basic templates
- knowledge - application which meets just for the articles and sections of articles
If you look in detail, the structure of the project will be as follows:
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
A few words about the project creation and application in the project. We used PyCharm development environment, which prepares the project with included core modules, including the admin, so I will talk about that was not included by default.
You should use the following command to create the application:
python manage.py startapp home python manage.py startapp knowledge
Configuration the settings.py
In order to have available application modules, you should connect them in the configuration file of the project.
INSTALLED_APPS = [ 'home.apps.HomeConfig', 'accounts.apps.AccountsConfig', ... ]
Model
The project uses two kinds of models:
- Section - Sections, which bring together all the articles one by one common feature, membership in a particular category
- Article - Articles
The model is described in the file models.py
For the development of these models have been used to inherit from the built-in Django Class Model. And use the model of the user User, as specified in the articles of the author of the number of registered users on the site.
from django.db import models from django.contrib.auth.models import User
Section
Section model consists of:
- Title
- URL - is used for the formation of the addresses on the site, that is not stored absolute paths, as part of the path to the list
- Description - is displayed in the top of the page before the list of articles
Let's look at the implementation of the model code:
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 class allows you to override some of the parameters of the model, which are directly related to the tables in the database. In this case determined, as will be called the Table.
The model has three fields, two of them have type CharField , which implies small recording limited number of input characters.
TextField type implies that there will be introduced a large enough random array of characters, the maximum size of which is not known beforehand.
Override str , and this is an override and not the new method makes it possible to return the title of the article that will appear in the admin panel. The fact is that if this method is not overridden, then all records in admin page will look like Section Object, and to understand where and what is to be very problematic when a large number of sections.
Article
The model consists of the following fields:
- Name
- Section - a foreign key to the Section table, determines the articles belonging to a particular section
- Author - a foreign key to the Users table from which will choose the author
- Date - date and time of publication
- Content - text field, similar to the description like in the Section model
-
Status - I am assuming several statuses for articles currently used only two:
- Draft - the value 0
- Posted - the value 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
Register models in the admin
In order to be able to edit articles and sections of the admin, you must register them in the admin module. This is done in admin.py relevant application file.
from django.contrib import admin from .models import Section, Article admin.site.register(Section) admin.site.register(Article)
Migration
Wrote model, sure that the models have all the required fields? Then you need to make a database migration. To do this, execute the following commands.
python manage.py makemigrations python manage.py migrate
Note
Primary Key in the general case is entered automatically and is auto-increment, so we do not indicate it.
Templates
Templates Django's just a wonderful thing, especially when you consider that they can be inherited, and certain blocks will be overridden.
The project created a basic template base.html home application, from which all the other pages were inherited. Conditional template structure is as follows:
{% block head %} {% endblock %} {% block content %} {% block page %} {% endblock page %} {% block sidebar %} {% endblock %} {% endblock content %} {% block footer %} {% endblock %}
In this case, there are five units, which can be overridden during inheritance patterns in other pages.
index.html
This template application's main page displays a list of all the sections. Use the extends statement, we specify that inherit from the base application template home. A duplicated page block of the base template, and prescribing the contents of this block we redefine the basic pattern making the information we need for a particular page.
As you can see, in the Django template language used the following constructions: if, for, url. But where did the variables section_list and section ? - Section_list passed as context values in a template in preparing the data in the presentation (view). After ensuring that there is a list of sections, we go through all the items in the list by substituting values into the template. Since the model section corresponds to Section, the corresponding fields of the model name are picked up automatically.
With regard to the url , then the operator indicates that it is necessary to take the address of the template knowledge application named section called, and we know that this address has a variable pattern, which we assign url object section. These templates are described in the file urls.py. We look at them later.
{% 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 %}
section.html
In the Template list, there is the formation of articles that match this razdlu. The context into the template variable section is transmitted, which contains information about the object section. We substitute the section title and description. Note that description is substituted with special argument safe, which indicates the format preservation. This must be done to save the html markup, otherwise the user will see instead a beautifully designed layout html code descriptions.
Also here it is a variant with a getting of information about all the articles that refer to this list, and this is done with the help of section.article_set.all call, that is, we take all the articles that have a foreign key to this section. Well, sort articles using dictsort specifying the parameter on which they are sorted.
A block if is checked the status of the article, that is, those items which are not published, will not be displayed.
With regard to the url , then again used the address template, but with two arguments.
{% 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
As you can see, the template for the article meager enough to add something about it.
{% extends 'home/base.html' %} {% block page %} <article> <h1>{{ article.article_title }}</h1> <p>{{ article.article_content|safe }}</p> </article> {% endblock %}
Note
If you look at the structure of the project, to see that the application contain more templates folder folders that have the same name as the application and page templates are already in them. This is done in order to accurately determine which template will be used. Django looks for templates in all folders and selects the first pattern that matches the name. And if the names are crossed, such as the index.html, the wrong template may be selected. Therefore namespace is used to determine what exactly the desired template.
View
In this case, the work with the presentation of sufficiently limited, so bring at once a full listing views.py file.
We inherit from the View class and override the method get, which is responsible for the execution of a GET request, that is, the user page request. We also import render_to_response methods, which will process the template in the required context, and get_object_or_404 , which will automatically return a 404 error if the object is found, the corresponding variable.
In EKnowledgeIndex we get everything Sections, which sorted by name and placed in the context of the name section_list, you remember that this variable was used in the template index.html .
In ESectionView already taken concrete section, the argument that is passed to the requested url. kwargs just responsible for variables that delaminate from the url of the template specified in the file urls.py.
In EArticleView everything is much more interesting. The fact that the two variables used url template, but for the article is enough to make a request for id, then have a Primary Key, which is passed to the 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 templates
Well, all that you need to write, but there was quite a bit to make it work, namely to configure url patterns, requests will be processed on that.
A feature of Django is that these templates are checking on regular expressions, and are not derived from models of controllers. For me personally, this approach proved to be clear and transparent, and I like him. So let's see how to revitalize our pages.
mysite/mysite/urls.py
First we need to set patterns in mysite / mysite / urls.py file that will determine which application to send a request. Here you can see that there is a trend in home application, there is shown the main page of the site, but I will not go into a description of the parts because of it we do not speak in this article. There is also a trend in the admin site and application knowledge, which is responsible just for the sections and articles.
A include , connected urls.py files in the home and knowledge applications.
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), ]
mysite/knowledge/urls.py
app_name
is responsible for the namespace in the templates. Remember? Just above the template was recording
'knowledge: section'
.
Well, regular expressions define what and where will be sent. With regard to records
and
Well, name specifies a URL template name, that is the second part in the 'knowledge: section' .
And finally, I would like to note is the ^ symbol, which is present in the template. With it has discarded the recognized part of the template. That is, in these url is also present in the early knowledge /, which was previously recognized in mysite / mysite / urls.py.
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') ]
For Django I recommend VDS-server of Timeweb hoster .
Спасибо за ваши статьи. Очень понятно и качественно пишите. Есть пара моментов в данной статье, которые мне кажутся спорными. Например, именование полей внутри моделей(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: в джанго - недавно, неделю.
Я дура. Разобралась. Но, остаюсь вашим читателем)