Jak zrobić domyślną kategorię?

0

Hej,

Bawię się frameworkiem Django i nie bardzo mam pomysł jak zrobić by posty dodane jako bez kategorii lądowały w domyślnej kategorii Uncategorized. Mam takie coś w pliku models.py:

from django.db import models
from django.contrib.auth.models import User


class Category(models.Model):
    name = models.CharField(max_length=200)


class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    published = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT, default=0) # Kategoria 0 nie istnieje w momencie wykonywania migracji

Każdy artykuł ma mieć możliwość posiadania więcej niż jednej kategorii, te artykuły, które nie posiadają kategorii mają mieć kategorię domyślną Uncategorized. Dodatkowo chcę aby nie można było użyć kategorii Uncategorized razem z innymi kategoriami. Ma ktoś jakiś pomysł jak to ogarnąć?

Będę wdzięczny za pomoc

0
lester29 napisał(a):

Hej,

Bawię się frameworkiem Django i nie bardzo mam pomysł jak zrobić by posty dodane jako bez kategorii lądowały w domyślnej kategorii Uncategorized. Mam takie coś w pliku models.py:

[...]
Każdy artykuł ma mieć możliwość posiadania więcej niż jednej kategorii, te artykuły, które nie posiadają kategorii mają mieć kategorię domyślną Uncategorized. Dodatkowo chcę aby nie można było użyć kategorii Uncategorized razem z innymi kategoriami. Ma ktoś jakiś pomysł jak to ogarnąć?

Rozumiem o co Ci chodzi, chciałbyś mieć taką "widmo-kategorię", która widnieje pod modelami które nie mają kategorii, i tylko pod nimi.

No więc, pojawia się pytanie: czy tą kategorię Uncategorized na ten moment potrzebujesz tylko w aplikacji: np w widoku, w logice, etc; czy również potrzebujesz ją w bazie? Pytam o to, czy chcesz mieć sposób zeby automatycznie w widoku pokazać Uncategorized jak coś nie ma kategorii (to byłoby najprostsze); czy chcesz np w ORM django robić filtry i join'y na modelach które mają Uncategorized? To będzie trudniejsze.

Jeśli to pierwsze - i po prostu chcesz w aplikacji pokazać Uncategorized, to po prostu nie dodawaj tego do bazy i już. Wszędzie gdzie zwracasz kategorie, dodaj ifa if len(categories) == 0: return ['Uncategorized']. To że Twoja aplikacja obsługuje jakąś kategorie, nie znaczy żaraz że musi ona istnieć w bazie - baza danych to jedynie persystencja, to nie jest jakieś źródło prawdy. Zwrócenie Uncategorized, jeśli nie masz żadnych categorii np w widoku albo endpoincie djangowym jest całkowicie normalne.

Więcej informacji możesz znaleźć tutaj: https://docs.djangoproject.com/en/4.1/topics/db/examples/many_to_one/

0
Riddle napisał(a):

czy chcesz np w ORM django robić filtry i join'y na modelach które mają Uncategorized? To będzie trudniejsze.

To drugie raczej. Dasz jakieś wskazówki jak to zrobić?

0
lester29 napisał(a):
Riddle napisał(a):

czy chcesz np w ORM django robić filtry i join'y na modelach które mają Uncategorized? To będzie trudniejsze.

To drugie raczej. Dasz jakieś wskazówki jak to zrobić?

Ale to drugie raczej, bo wydaje Ci się to lepszym wyjściem? Czy masz konkretny powód ku temu?

Chodzi o to, że (jeśli dobrze rozumiem co chcesz zrobić), to Uncategorized to nie jest taka kategoria jak pozostałe, więc nie powinna być dodana do relacji. Jak rozumiem "zwykłe" kategorie można dodawać i usuwać, ale Uncategorized nie - Uncategorized ma być albo nie być, w zależności od tego czy kategorie istnieją - moim zdaniem to byłby bardzo zły pomysł żeby zrobić Unategorized żeby to była kategoria.

0

Myślałem żeby umieścić Uncategorized w bazie żeby móc sobie odfiltrować posty bez kategorii w widokach czy w python manage.py shell.

Co do wartości Uncategorized, powinienem dać możliwość null=True w polu category w models.Article i w cascade dać SET_NULL żeby być w stanie obsługiwać posty bez kategorii?

46

A nie prościej zrobić coś takiego (Zakładając, że chcesz rozróżnić który obiekt ma kategorię a który nie):

pole category zrobić opcjonalne i dorzucić metodę do modelu w stylu

def has_category(self):
  return self.category is not None

Potem w widoku / templatce filtrujesz sobie co tam potrzebujesz.

0
lester29 napisał(a):

Myślałem żeby umieścić Uncategorized w bazie żeby móc sobie odfiltrować posty bez kategorii w widokach czy w python manage.py shell.

No, czyli nie ma konkretnego powodu żeby dodać to do bazy.

lester29 napisał(a):

Co do wartości Uncategorized, powinienem dać możliwość null=True w polu category w models.Article żeby być w stanie obsługiwać posty bez kategorii?

Nie.

Rozwiązanie

Jak rozumiem, masz relację jeden-do-wielu, czyli jeden artykuł może mieć wiele kategorii. Może też mieć 0 kategorii - takie artykuły chcesz handlować w szczególny sposób.

Żeby zwrócić artykuły bez kategorii możesz użyć np:

uncategorized_articles = Article.objects.annotate(c=Count('categories')).filter(c__gt=0)
0

To w końcu category powinno być w Article czy post w Category? Jak dobrze rozumiem to ForeignKey odpowiada za relację jeden do wielu.

45
lester29 napisał(a):

To w końcu category powinno być w Article czy post w Category? Jak dobrze rozumiem to ForeignKey odpowiada za relację jeden do wielu.

W django masz coś takiego jak "reverse foreign key relation". Wystarczy, że zawołasz z poziomu Category coś w stylu Category.article_set

0
ledi12 napisał(a):
lester29 napisał(a):

To w końcu category powinno być w Article czy post w Category? Jak dobrze rozumiem to ForeignKey odpowiada za relację jeden do wielu.

W django masz coś takiego jak "reverse foreign key relation". Wystarczy, że zawołasz z poziomu Category coś w stylu Category.article_set

Mógłbyś podesłać link do dokumentacji?

0

Chodzi mi o to, czy powinienem zrobić tak

class Category(models.Model):
    name = models.CharField(max_length=200)


class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    published = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='categories')

czy tak

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    published = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)


class Category(models.Model):
    name = models.CharField(max_length=200)
    articles = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articles')
0
lester29 napisał(a):

Chodzi mi o to, czy powinienem zrobić tak

class Category(models.Model):
    name = models.CharField(max_length=200)


class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    published = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='categories')

czy tak

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    published = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)


class Category(models.Model):
    name = models.CharField(max_length=200)
    articles = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articles')

Zakładam że nie chcesz mieć duplikacji w kategoriach.

Jeśli wybierzesz opcję pierwszą, to jeden artykuł będzie mógł mieć jedną kategorię.
Jeśli wybierzesz opcje drugą, to jedna kategoria będzie mogła mieć jeden artykuł, czyli jeśli dwa artykuły miałyby mieć tą samą kategorię, to musiałbyś ją dodać dwa razy.

Jest jeszcze trzecia opcja, możesz zrobić joining table i zrobić relację wiele-do-wielu.

Pytanie się sprowadza do tego:

  • czy chcesz mieć duplikacje w bazie
  • czy chcesz żeby jeden artykuł mógł mieć wiele kategorii?
0
Riddle napisał(a):
  • czy chcesz mieć duplikacje w bazie

Jeśli to konieczne dla zapewnienia relacji to nie mam nic przeciwko. Jednak mimowszystko preferuję unikanie duplikatów. Jak ty byś sugerował? Co sądzisz o zastosowaniu relacji wiele-do-wielu?

Riddle napisał(a):
  • czy chcesz żeby jeden artykuł mógł mieć wiele kategorii?

Tak. Oprócz tego te same kategorie może mieć wiele artykułów.

0
lester29 napisał(a):
Riddle napisał(a):
  • czy chcesz mieć duplikacje w bazie

Jeśli to konieczne dla zapewnienia relacji to nie mam nic przeciwko. Jednak mimowszystko preferuję unikanie duplikatów. Jak ty byś sugerował? Co sądzisz o zastosowaniu relacji wiele-do-wielu?

Riddle napisał(a):
  • czy chcesz żeby jeden artykuł mógł mieć wiele kategorii?

Tak. Oprócz tego te same kategorie może mieć wiele artykułów.

No to skoro tak, to żadne z tych podejść się nie nadaje. Użyj tego: https://docs.djangoproject.com/en/4.1/topics/db/examples/many_to_many/

I nie dodawaj Uncategorized do bazy.

0

Dzięki za pomoc :) Chyba pora podszkolić się nieco w bazach danych

0
lester29 napisał(a):

Dzięki za pomoc :) Chyba pora podszkolić się nieco w bazach danych

A musisz używać relacyjnej bazy danych? Może mógłbyś użyć czegoś prostszego.

0

Co niby prostszego mógłby użyć do aplikacji napisanej w Django jako bazę?

0
anonimowy napisał(a):

Co niby prostszego mógłby użyć do aplikacji napisanej w Django jako bazę?

Mongo.

3

Aha, ziomek jest początkujący i nie ogarnia relacyjnej bazy danych i podstaw Django a ty mu proponujesz Mongo do Django...

0
anonimowy napisał(a):

Aha, ziomek jest początkujący i nie ogarnia relacyjnej bazy danych i podstaw Django a ty mu proponujesz Mongo do Django...

No, i złego w tym jest co?

Relacyjne bazy to nie jest najprostsza persystencja, wymaga ORM'ów albo pisania SQL'i, wiedzy o relacjach. A są sposoby na persystencje gdzie po prostu bierzesz swoje dane i zapisujesz tak jak są.

1
  1. Relacyjna baza bardziej pasuje do tego problemu.
  2. Django wymaga relacyjnej bazie w praktycznie każdym projekcie
  3. Jeśli chce iść w kierunku Django to i tak jest to nieunikniona nauka (zarówno ORM jak i SQL)
0
anonimowy napisał(a):
  1. Relacyjna baza bardziej pasuje do tego problemu.

Ponieważ?

Gość chce po prostu mieć kategorię w Article, mongo również się do tego nadaje.

  1. Django wymaga relacyjnej bazie w praktycznie każdym projekcie

Brednie.

Owszem, jak setupujesz defaultowy projekt z django, to on z defaulta podepnie Ci relacyjną, ale można to łątwo zmienić.

  1. Jeśli chce iść w kierunku Django to i tak jest to nieunikniona nauka (zarówno ORM jak i SQL)

Brednie również. Można korzystać z Django jako integracji z HTTP i podpiąć sobie swoją persystencje.

Zobacz jak łatwo jest podpiąć mongo pod django: https://www.mongodb.com/compatibility/mongodb-and-django

0

To pokaż mi 5 projektów w Django (mogą być open source lub komercyjne), które nie korzystają z relacyjnej bazy danych. Pracuję od 10 lat z Django w największych projektach na świecie (zarabiających milardy $) i nigdy się z czymś takim nie spotkałem. Ty z tego co wiem nie jesteś ekspertem w Django

1

Rozumiem, że chcesz mieć kategorię "Uncategorized", ale ja bym po prostu dopuszczał wartości NULL w polu category.

category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)

Jeśli chcesz potem filtrować, wystarczy że zrobisz:

Article.objects.filter(category__isnull=True)

i tak bym to rozwiązał. Również zostałbym przy relacyjnej bazie danych

0
anonimowy napisał(a):

To pokaż mi 5 projektów w Django (mogą być open source lub komercyjne), które nie korzystają z relacyjnej bazy danych. Pracuję od 10 lat z Django w największych projektach na świecie (zarabiających milardy $) i nigdy się z czymś takim nie spotkałem. Ty z tego co wiem nie jesteś ekspertem w Django.

No to z wieloma rzeczami musiałeś się nie spotkać, jest nawet connector gotowy: https://github.com/doableware/djongo Więc jak widać, przejście na noSql, nie oznacza odejścia od ORM'u djangowego.

Ten connector na samym githubie ma
screenshot-20230117135024.png
tyle użyć, więc masz nawet więcej niż 5 przykładów ;)

0

Chodzi mi o projekty, które korzystają z tego. To, że jest to możliwe to wiadome. Dodatkowo ta biblioteka to wrapper na ORM czyli i tak pozostaje nauka ORM

Sam pisałeś przecież "Relacyjne bazy to nie jest najprostsza persystencja, wymaga ORM'ów albo pisania SQL'i, wiedzy o relacjach." czyli sam obalasz swój arugment

1 użytkowników online, w tym zalogowanych: 0, gości: 1