Iniciante: Tentando entender como os aplicativos interagem em Django

votos
28

Eu só tenho feito trabalho através dos tutoriais Django para o segundo tempo, e estou entendendo as coisas muito mais claramente agora. No entanto, estou ainda não está claro como os aplicativos dentro de um site interagir um com o outro.

Por exemplo, digamos que eu estou escrevendo um aplicativo de blog (uma atividade bastante popular, aparentemente). posts e comentários tendem a ir junto, e ainda assim eles são distintos o suficiente para que eles devem ser construídos em aplicativos separados, como é a filosofia geral de desenvolvimento Djano.

Considere o seguinte exemplo. Na realidade eu não iria realmente escrever o comentário me aplicativo, tão bom código para que já existe na web, mas isso é para fins de demonstração / prática:

mysite / blog / models.py

from django.db import models

class post(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=200)
    content = models.TextField()

mysite / comentários / models.py

from django.db import models
from mysite.blog.models import post

class comment(models.Model):
    id = models.AutoField()
    post = models.ForeignKey(post)
    author = models.CharField(max_length=200)
    text = models.TextField()

É o que eu escrevi acima, a importação de um modelo de outro aplicativo e configurá-lo como uma chave estrangeira, como Django aplicativos interagem? Ou há um melhor método diferente / para os aplicativos que compõem um site para interagir?

Atualize
Por recomendação de uma resposta, estou lendo a documentação para contrib.contenttypes. Se eu estou lendo isso corretamente, eu poderia reescrever meu exemplo comentário aplicativo como este:

from django.db import models  
from django.contrib.contenttypes.models import ContentType
from django.contrib.contentypes import generic

class comment(models.Model):  
    id = models.AutoField()  
    author = models.CharField(max_length=200)  
    text = models.TextField()  
    content_type = models.ForeignKey(ContentType)  
    content_object = generic.GenericForeignKey(content_type, id)  

Será que isso é correto?

Publicado 09/12/2008 em 18:25
fonte usuário
Em outras línguas...                            


4 respostas

votos
21

Dê uma olhada em Django built-in quadro contenttypes :

django.contrib.contenttypes

Ele permite que você desenvolver suas aplicações como unidades autônomas. Isto é o que os desenvolvedores Django usou para permitir Django built-in quadro comentário para anexar um comentário a qualquer modelo em seu projeto.

Por exemplo, se você tem algum objeto de conteúdo que deseja "unir" a outros objetos de conteúdo de diferentes tipos, como permitir que cada usuário para deixar uma estrela "favorito" em um post de blog, imagem ou perfil de usuário, você pode criar um Favoritemodelo com um campo de relação genérica assim:

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Favorite(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

Desta forma, você pode adicionar uma Favoriteestrela de qualquer usuário a qualquer modelo em seu projeto. Se você deseja adicionar acesso à API através da classe modelo de destinatário que você pode adicionar um campo de relação genérica reversa no modelo de destinatário (embora isso seria "acoplamento" os dois modelos, o que você disse que queria evitar), ou fazer o lookup através do Favoritemodelo com o content_typee object_idda instância do destinatário, consulte os documentos oficiais para um exemplo.

Respondeu 09/12/2008 em 19:01
fonte usuário

votos
3

Não há nada de errado (IMHO) com fazer algum aplicativo dependente de outra. Afinal de contas, os aplicativos são apenas operações em um conjunto de modelos. você só tem que sempre estar ciente de qual aplicativo depende de qual aplicativo (eu acho que você poderia chamar isso de um mapa de dependência).

Você pode conseguir acoplamento com o quadro contenttypes. Ele permite que um aplicativo para ser verdadeiramente portátil / pluggable mas ainda integrado com outras aplicações.

Eu escrevi um aplicativo de comentários (sim, eu re-inventou a roda), que podem ser integrados em qualquer outro aplicativo, com algumas linhas no modelo da página onde os comentários devem ser enviados (usando marcas personalizadas).

Digamos que você queira um modelo de "thread" para ser conectável em qualquer outro modelo. A ideia é criar e chave estrangeira genérico (consulte a documentação do Django sobre isso), e escrever uma pequena função que leva qualquer objeto e retorna um "thread" correspondente a ele (ou cria um se necessário), e escrever uma etiqueta modelo personalizado que utiliza essa funcionalidade, por exemplo {% get_thread for arbitrary_object as thread %}. Todas as mensagens estão relacionadas com um tópico, que está relacionado com o objeto, que pode ser de qualquer tipo.

Você pode pensar do objeto "thread" como uma espécie de um proxy, então ao invés de ter um posto de estar relacionado a um certo "artigo" ou um "post", é apenas relacionado com um fio, que é abstrato em um sentido , o que é um fio? É apenas uma coleção de mensagens. O fio permite, em seguida, se a estar relacionada com qualquer objeto, independentemente do seu tipo. (embora não mais do que isso, pode armazenar informações extra, como habilitar / desabilitar Anon. mensagens, fechando / abrindo comentários na página, etc ..)

EDITAR

Veja como você pode criar uma chave estrangeira genérico com o quadro tipos de conteúdo:

from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType

class Thread( models.Model ):
    object_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('object_type', 'object_id')

Você pode torná-lo mais "transparente", explorando a interface implícito "comum" que o Django assume todos os objetos implementar ..

    #inside the Thread class:
    def __unicode__(self):
        return unicode(self.object)
    def get_absolute_url(self):
        return self.object.get_absolute_url()
Respondeu 09/12/2008 em 19:35
fonte usuário

votos
3

"É o que eu escrevi acima, a importação de um modelo de outro aplicativo e configurá-lo como uma chave estrangeira, como Django aplicativos interagem?"

Sim. Funciona para mim.

Temos cerca de 10 aplicações que tomam emprestado e para trás entre si.

Isto leva a uma espécie de dependência em nosso script de teste de unidade.

Se parece com isso.

  • "propriedade". Nós temos uma aplicação de propriedade de dados simples que define alguns conceitos de propriedade do núcleo que outras aplicações dependem. Existem algumas tabelas simples aqui.

  • "coisa". [Não é o nome verdadeiro]. Nossa aplicação coisa tem elementos de dados pertencentes a diferentes grupos de usuários. Na verdade, existem várias tabelas complexas do modelo para este aplicativo. Isso depende de "propriedade".

  • "tabelas". [Não é o nome verdadeiro]. Alguns de nossos usuários a criar bastante complexos modelos off-line (provavelmente com planilhas) e fazer o upload dos resultados dessa modelagem em "mesas". Isto tem um conjunto de tabelas bastante complexos. Isso depende de "propriedade".

  • "resultado". [Não é o nome verdadeiro]. Nossos resultados são baseados em coisas que têm proprietários. Os resultados são baseados em coisas e tabelas, e são respostas a pedidos de clientes. Isto não é muito complexo, talvez apenas dois ou três mesas centrais. Depende de "coisas" e "table". Não, ele não totalmente stand-alone. No entanto, é sujeito a mais mudanças do que as outras coisas de que depende. É por isso que é separado.

  • "em processamento". Nós agendar e monitorar os trabalhos de grandes lotes. Esta é nesta aplicação. É muito genérico, e pode ser usado em uma variedade de maneiras. Ele fica completamente sozinho.

  • "bem vinda". Temos um app "bem-vindo", que apresenta um monte de páginas em sua maioria estáticos. Isto não tem muitas mesas. Mas é, por si segunda encarnação porque o primeiro era demasiado complexo. Ele fica completamente sozinho.

A única relação entre os aplicativos dependentes é alguns nomes de tabela. Enquanto nós preservar essas tabelas (e suas chaves), podemos reorganizar outros aplicativos que acharmos conveniente.

Respondeu 09/12/2008 em 19:06
fonte usuário

votos
2

Seu código parece correto. Gostaria de manter o post eo comentário em um blog de aplicativo embora. Não estou dizendo que esta é a forma como Django, mas esses modelos estão perto o suficiente para ser no mesmo aplicativo.

Como dividir o projeto

Gostaria de separar um aplicativo se;

  • I planejar para projetá-lo resuable. (E tentar acoplamento frouxo)
  • (Para grandes projetos) Trata-se de uma grande seção do projeto.

Por outro lado; tendo muitos aplicativos pequenos (como um app com um único modelo e dois pontos de vista) é difícil de ler e manter IMHO.

Como Apps devem interagir

Isso depende do tipo de projecto e o tipo do aplicativo novamente. Por exemplo, se uma aplicação está implicitamente dependente de outro (isto é, não genérico) importar e usando referências da outra aplicação é aceitável. Neste caso, o segundo aplicativo pode ser instalado sozinho, mas o primeiro é necessário a presença do segundo.

Se você quiser fazer um aplicativo altamente reutilizáveis e genérico, como um aplicativo comentando, pode ser necessário para integrar algum mecanismo de configuração. Talvez algumas novas configurações ou configuração URL adicional, ou uma directiva / método especial em seus modelos ... django.contrib.adminé um bom exemplo para isso.

Aplicativos não devem interagir, se não é necessário embora. Projetando aplicativos para evitar acoplamento desnecessário é muito útil. Ele melhora a flexibilidade da sua aplicação e faz com que seja mais sustentável (mas possivelmente com um custo mais elevado na integração).

Respondeu 09/12/2008 em 18:45
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more