20

Kilka razy przeglądałem dokumentację Django dotyczącą frameworku contenttypes, a ja po prostu nie rozumiem tego wystarczająco dobrze, aby wdrożyć ogólne relacje w moim projekcie. Szukałem przykładów online lub samouczków dotyczących tej sprawy, ale nie mogę znaleźć ani jednego. Zadzwoń do mnie głupio, ale potrzebuję pomocy w tej sprawie (proszę nie odpowiadać, po prostu łącząc się z dokumentami). Opierając się na braku zasobów w Internecie, wierzę, że jeśli odpowiesz na to pytanie dokładnym przykładem, twoja odpowiedź może być najbardziej użytecznym przykładem do tej pory związanym z ogólnymi relacjami django (bonus!).Django: Przykład ogólnych relacji za pomocą struktury contenttypes?

Moje pytanie brzmi: czy ktoś może pokazać prosty przykład modeli i może kilka linii kodu pokazujących, jak interakcję z instancjami modelu ogólnego?


jako inspiracji, tutaj jest to, co uważam, że jest to bardzo powszechna sytuacja:

Witryna zawiera elementy multimedialne, które są w dużej mierze traktowane tak samo, ale różnią się nieco. Załóżmy na przykład, że istnieją elementy graficzne i wideo, a użytkownicy mogą "polubić" element lub "komentarz" do elementu. Podobieństwa i komentarze powinny być traktowane tak samo, niezależnie od tego, czy są one zamieszczane na obrazie lub elemencie wideo. Tak więc, jeśli istnieje ItemView do oglądania obrazu lub wideo w albumie użytkownika, następujące rodzaje połączeń są możliwe: mediaitem.comments.all() lub len(mediaitem.likes.all()) lub comment.user_who_commented, bez konieczności sprawdzania, który rodzaj elementu multimedialnego jest (zdjęcie lub wideo) .

wierzę, że trzeba sześć modeli na to:

  • Streszczenie MediaItem klasa
  • dwa różne rodzaje pozycji mediów: ImageItem i VideoItem
  • Abstrakt MediaItemActions klasa
  • Dwa różne rodzaje działań, które można wykonać w odniesieniu do elementów multimedialnych: Like i Comment

Jeśli wiesz, jak korzystać z tej funkcji Django, proszę pokazać nam pełny przykład! Czuję, że byłoby to niezwykle potężne narzędzie i chciałbym go użyć w mojej aplikacji. Im bardziej wyraźne, tym lepiej.

Odpowiedz

5

Twój przypadek użycia brzmi bardzo podobnie do (teraz przestarzałego) Django comments framework. Jeśli sprawdzisz models, zobaczysz, jak używać relacji ogólnej w BaseCommentAbstractModel - zauważ, że potrzebujesz wszystkich trzech pól, ForeignKey do ContentType, pola do przechowywania obiektów 'pk s oraz pola GenericForeignKey.

Co do tego, jak wyszukiwać obiekty według GenericForeignKey, można zobaczyć niektóre przykłady w projekcie template tags. Zobacz na przykład metodę get_query_set w BaseCommentNode, która pobiera komentarze przez kwerendę dotyczącą typu zawartości i obiektu docelowego.

def get_query_set(self, context): 
    ctype, object_pk = self.get_target_ctype_pk(context) 
    if not object_pk: 
     return self.comment_model.objects.none() 

    qs = self.comment_model.objects.filter(
     content_type = ctype, 
     object_pk = smart_text(object_pk), 
     site__pk  = settings.SITE_ID, 
    ) 
1

Inną opcją jest Polymorphic Models. Nie powiem, że tak powinieneś iść, ale może to być opcja.

Jestem fanem generycznych kluczy obcych i modeli polimorficznych. Modele polimorficzne działają najlepiej w tych scenariuszach, w których występuje wiele podobieństw w modelach.

3

Rzeczywiście mam bardzo podobną sytuację w jednym z moich projektów, z różnymi rodzajami mediów.

class TaggedItem(models.Model): 
    tag = models.SlugField() 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

class ReviewedItem(models.Model): 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 
    review = models.ForeignKey("Review") 

class CreativeWork(models.Model): 
    #other fields 
    keywords = generic.GenericRelation("TaggedItem",null=True, blank=True, default=None) 
    reviews = generic.GenericRelation("ReviewedItem",null=True, blank=True, default=None) 

class MediaObject(CreativeWork): 
    #fields 
class VideoObject(MediaObject): 
    #fields 
class AudioObject(MediaObject): 
    #fields 

Każdy plik wideo lub audio to obiekt MediaObject, który jest CreativeWork. CreativeWorks ma GenericRelation do tagów i recenzji. Teraz wszystko można oznaczyć lub sprawdzić.

Wszystko czego potrzebujesz to "akcja", aby mieć klucz ForeignKey do ContentType. Niż dodać GenericRelation do swojego modelu. Właściwie to django.docs jest całkiem pomocny :) Ale jeśli nie nadzieja, to pomaga.

Powiązane problemy