Django- podział aplikacji na moduły [zamknięte]

Zacząłem dzisiaj pisać projekt, w którym nie mogę sobie poradzić z odpowiednim podziałem na moduły. Sytuacja ma się tak- jest model aplikacji A, który musi być powiązany w relacji jeden do jednego z jednym z modeli B, C, lub D. Natomiast do modeli B, C, D będą relacją wiele do jednego dowiązane inne, różne dla każdego modelu elementy.

Najchętniej podzieliłbym cały projekt tak, żeby modele B, C, D były w osobnych aplikacjach- ale wtedy przy rozbudowie całego projektu, jakby doszedł model E, to ręcznie trzeba by zmieniać A. Natomiast, jeśli B, C, D wrzucę do jednej aplikacji i uda mi się skorzystać z ContentTypes, to wtedy zrobi się straszy bałagan w aplikacji, do której to wrzucę.

Obrazowo mniej więcej ma to wyglądać tak:

alt text

Powód zamknięcia: Udzielono odpowiedzi na pytanie, poprawna odpowiedź została zaakceptowana

  • Nie do końca wiem dlaczego użycie GenericRelation wymusza, żeby B,C i D były w jednej aplikacji. Może czegoś nie widzę.

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes import generic
    
    class A(models.Model):
        foo = models.CharField(max_length=42)
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        parent = generic.GenericForeignKey('content_type', 'object_id')
    
        class Meta:
             # każde A może mieć dokładnie 1 obiekt
             # żadne dwa A, nie mogą być powiązane z tym samym => 1-1
             unique_together = ('object_id', 'content_type')
    

    Można wprowadzić jakieś ograniczenia w clean() na to z jakimi obiektami może się wiązać klasa A. Na przykład tylko z takimi, których klasy mają odpowiedni atrybut dzięki czemu nie musiałbyś ich wszystkich tu wymieniać (można też użyć mechanizmu ABC).

    Przykład z walidacją:

    import abc
    from django.core.exceptions import ValidationError
    
    class TaggableModel(object):
        __metaclass__ = abc.ABCMeta
    
    class TaggedItem(Model):
        # pola jak w A plus
        def clean(self):
            if not issubclass(self.content_type.model_class(), TaggableModel):
                raise ValidationError("Objects of type %r is not taggable" % self.content_type) 
    
    # w innej aplikacji
    
    class B(Model): pass
    TaggableModel.register(B)
    

    PS. Przykład nietestowany, ale idea chyba jest jasna.

  • A gdzie pytanie? Bo na razie opisałeś co zrobiłeś ;)

    Podejrzewam, że chodzi Ci o dziedziczenie. Napisz sobie model A i potem niech modele B, C i D z niego dziedziczą. Pisząc model E dziedziczący z A zawsze możesz wprowadzić dodatkowe zmiany.

    class KlasaA(models.Model):
        name = models.CharField(max_length=100)
    
        def taramtam(self):
            return self.name
    
    class KlasaB(KlasaA):
        pass
    
    class KlasaE(KlasaA):
        info = models.TextField()
    
        def taramtam(self):
            return "%s %s" % (self.name, self.info)
    

    Dzięki temu KlasaB jest wierną kopią KlasyA, a KlasaE ma dodane pole info i zmienioną metodę taramtam. Jeśli KlasaA jest tylko wzorcem i nie ma tworzyć osobnej tabeli w bazie danych, to dopisz do niej coś takiego:

    class KlasaA(models.Model):
        # tutaj definicja klasy
    
        class Meta:
            abstract = True
    

    Zainteresuj się też modelami pośredniczącymi (proxy). Jest pewna różnica w stosunku do abstrakcyjnych klas bazowych wspomnianych wcześniej :)

Zaloguj się, aby dodać swoją odpowiedź