GithubHelp home page GithubHelp logo

m2m's Introduction

Задание

Есть небольшой новостной сайт.

Начальное состояние

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

Вывод тегов разделов

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

В админке необходимо реализовать создание разделов и для страницы Редактирование статьи добавить возможность указывать разделы. Необходимо также реализовать проверку на наличие одного и только одного основного раздела.

Админка

Примечание

  • Tag — просто тег, только его название, ничего более;
  • Article — статья с текстом, заголовком, картинкой и пр. + набор тегов (многие ко многим);
  • Scope — таблица-связка между статьей и тегом. Именно здесь должно быть свойство is_main.

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

{% for scope in article.scopes.all %}
    <span class="badge {% if scope.is_main %}badge-primary{% else %}badge-secondary{% endif %}">{{ scope.tag.name }}</span>
{% endfor %}

Подсказки

Чтобы реализовать на странице редактирования объекта возможность редактировать связи через таблицу многие-ко-многим, в админке используйте свойство inlines:

from django.contrib import admin

from .models import Object, Relationship


class RelationshipInline(admin.TabularInline):
    model = Relationship


@admin.register(Object)
class ObjectAdmin(admin.ModelAdmin):
    inlines = [RelationshipInline]

Вместо Object должна быть модель, имеющая связь многие-ко-многим, а вместо Relationship должна быть модель связи, указанная как through для связи. Подробнее: https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.ManyToManyField.through. Все остальное django реализует автоматически.

Однако в этой задаче вам потребуется добавить дополнительную проверку при сохранении объекта. Для этого в объекте Inline можно переопределить атрибут formset, который должен указывать на специальный класс типа BaseInlineFormSet, нужный для обработки списка однотипных форм, каждая для своей связи. Воспользуйтесь следующим примером с переопределением метода clean, указанного в качестве formset класса:

from django.contrib import admin
from django.core.exceptions import ValidationError
from django.forms import BaseInlineFormSet

from .models import Object, Relationship


class RelationshipInlineFormset(BaseInlineFormSet):
    def clean(self):
        for form in self.forms:
            # В form.cleaned_data будет словарь с данными
            # каждой отдельной формы, которые вы можете проверить
            form.cleaned_data
            # вызовом исключения ValidationError можно указать админке о наличие ошибки
            # таким образом объект не будет сохранен,
            # а пользователю выведется соответствующее сообщение об ошибке
            raise ValidationError('Тут всегда ошибка')
        return super().clean()  # вызываем базовый код переопределяемого метода


class RelationshipInline(admin.TabularInline):
    model = Relationship
    formset = RelationshipInlineFormset


@admin.register(Object)
class ObjectAdmin(admin.ModelAdmin):
    inlines = [RelationshipInline]

Для упорядочивания моделей по умолчанию удобно воспользоваться свойством Meta класса ordering:

class Article(models.Model):
    ...

    class Meta:
        verbose_name = 'Статья'
        verbose_name_plural = 'Статьи'
        ordering = ['-published_at']

Документация по проекту

Для запуска проекта необходимо

Установить зависимости:

pip install -r requirements.txt

Провести миграцию:

python manage.py migrate

Загрузить тестовые данные:

python manage.py loaddata articles.json

Запустить отладочный веб-сервер проекта:

python manage.py runserver

m2m's People

Contributors

citylamer avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.