Django runtime error: conflicting models. Best approach to split models.py file into models subfolder

Viewed 315

I have my django apps inside apps folder. Due to multiple article types I decided to split my models.py for the articles app and put it inside the models folder where each modelname.py file points to a model.

Problem: configuring syndication framework (as described in https://docs.djangoproject.com/en/3.2/ref/contrib/syndication/) causes a runtime error Conflicting 'news' models in application 'articles': <class 'articles.models.news.News'> and <class 'apps.articles.models.news.News'>.

Note: Before adding syndication framework functionality everything works just fine.
I tried: Adding app_label to the News model.

apps folder structure:

├── articles
│   ├── admin.py
│   ├── apps.py
│   ├── feeds.py
│   ├── __init__.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── articles.py
│   │   ├── categories.py
│   │   ├── news.py
│   │   ├── reviews.py
│   │   └── tags.py
│   ├── tests.py
│   ├── urls.py
│   └── views
│       ├── __init__.py
│       ├── news.py
├── conftest.py
├── education
├── __init__.py
├── users

/apps/articles/models/news.py:

from django.db import models

class News(models.Model):
    //
    // Model Fields
    //

    class Meta:
        ...
        app_label = 'articles'
        ...

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("articles:news_detail", kwargs={"slug": self.slug})

/apps/articles/feeds.py:

from django.contrib.syndication.views import Feed
from django.utils.translation import gettext_lazy as _
from .models.news import News


class NewsEntriesFeed(Feed):
    title = _("News")
    link = "/news/"
    description = _("Latest news")

    def items(self):
        return News.objects.order_by('-publish_date')[:5]

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.lead

/apps/articles/urls.py:

from django.urls import path
from .views.news import NewsDetailView, NewsListView
from .feeds import NewsEntriesFeed

app_name = "articles"

urlpatterns = [
    path("news/", NewsListView.as_view(), name="news_list"),
    path("news/<str:slug>/", NewsDetailView.as_view(), name="news_detail"),
    path("feed/rss", NewsEntriesFeed(), name="news_feed"),
]

/apps/articles/apps.py

from django.apps import AppConfig


class ArticlesConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'articles'

INSTALLED_APPS

INSTALLED_APPS = [
   ...
   ...
   "apps.articles.apps.ArticlesConfig",
   ...
]
1 Answers

I found the solution in https://www.webforefront.com/django/modelsoutsidemodels.html. According to listing 7-42 (first approach) steps to split models into models directory are:

  1. Create models directory inside the specific app folder, alongside models.py file which you want split
  2. Create __init__.py inside models folder
  3. Next, inside the models folder create multiple .py files with Django models declared as they would typically be done inside models.py. You can have as many models as needed in each .py file and as many .py files as you deem necessary (e.g. one model per file)
  4. the __init__.py file must make a relative import for each of the models -inside .py files - to make them visible to the app
  5. This one-line syntax - from .<file> import <model_class> - must be used in __init__.py for every model declared in .py files inside the models folder.

Note: for more information and tips, see https://www.webforefront.com/django/modelsoutsidemodels.html

Related