Newbie: Trying to understand how apps interact in Django

I just finished with the Django tutorials for the second time and now I understand things much more clearly. However, I still don't understand how the applications within the site interact with each other.

For example, let's say I'm writing a blog app (a pretty popular activity, apparently). Blog posts and comments tend to go together, and yet they are clear enough to be built into separate applications, as well as the overall Djano development philosophy.

Consider the following example. Actually I wouldn't actually write a comment app, as good code for this already exists on the internet, but this is for demo / practical purposes:

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 / comments / 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()

      

This is what I wrote above, importing a model from another application and setting it as a foreign key, how do Django applications interact? Or is there another / better method for apps that contain a site to interact with?

Update
Following a recommendation in one answer, I am reading the documentation for contrib.contenttypes. If I read this correctly, I could rewrite my comments app to the example like this:

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)  

      

Is it correct?

+28


source to share


4 answers


Take a look at the built in django content structure :

django.contrib.contenttypes

This allows you to develop applications as standalone. This is what the django devs used to create django inline comment framework to add comment to any model in your project.



For example, if you have a content object that you want to "attach" to other content objects of different types, for example, for each user to leave a "favorite" star in a blog, image or user profile, you can create a model Favorite

with a common field relationship as follows:

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')

      

This way you can add an asterisk Favorite

from any user to any model in your project. If you want to add API access through the recipient model class, you can either add the inverse of the common fields relationship to the recipient model (although this will "bind" the two models that you said you wanted to avoid), or search the model Favorite

with help content_type

and object_id

recipient instance, see official docs for example.

+21


source


"This is what I wrote above, importing a model from another application and setting it as a foreign key, how do Django applications interact?"

Uh-huh. Works for me.

We have about 10 applications that are interconnected.

This leads to some dependency in our unit test script.



It looks like this.

  • "own". We have a simple data ownership application that defines some basic ownership concepts that other applications depend on. There are some simple tables here.

  • "thing". [Not real name]. Our application has items of data belonging to different user groups. There are actually several complex model tables for this application. It depends on "ownership".

  • "tables". [Not real name]. Some of our users create fairly complex stand-alone models (possibly with spreadsheets) and load the results of that simulation into “tables”. This is a cluster of fairly complex tables. It depends on "ownership".

  • "result"

    ... [Not real name]. Our results are based on things that have owners. The results are based on things and tables and are responses to customer inquiries. It's not too hard, maybe just two or three main tables. It depends on "things" and "table". No, it is not completely self-contained. However, it is subject to more changes than other things on which it depends. This is why it splits.

  • "treatment". We plan and control large batch jobs. It's in this app. It's really generic and can be used in a variety of ways. He totally stands alone.

  • "Welcome". We have a welcome application, which is a bunch of mostly static pages. It's not too many tables. But this is the second incarnation on him, because the first was too difficult. He totally stands alone.

The only relationship between dependent applications is some table names. As long as we keep these tables (and their keys), we can arrange other applications as we like.

+3


source


There is nothing wrong (imho) for an application to depend on another. After all, applications are just operations on a set of models. you just need to always know which application depends on which application (I think you could name this dependency map).

You can achieve a loose connection with the content base. This app can be truly portable / pluggable, but still integrated with other apps.

I wrote a commenting app (yes, I invented the wheel) that can be integrated into any other multi-line app in the page template where comments are to be posted (using custom tags).

Let's say you want the model stream to be connected to any other model. The idea is to create a shared key (see django documentation) and write a small function that takes any object and returns a stream corresponding to it (or creates one if needed), and write your own template tag that uses this functionality , for example {% get_thread for arbitrary_object as thread %}

. All messages refer to a thread that is associated with an object, which can be of any type.

You can think of the "stream" object as a kind of proxy, so instead of the post being associated with a specific "article" or "blog post", it is simply associated with a stream, which is abstract in a sense, what is a thread ? It's just a collection of messages. The thread then lets you associate itself with any object, regardless of its type. (although it does more than that, it may contain additional information like allow / deny anonymous posts, close / open comments on a page, etc.)

EDIT

Here you can create a generic foreign key with a content type map:

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')

      

You can make it more "transparent" by using the implicit "generic" interface, which django assumes that all objects are implemented.

    #inside the Thread class:
    def __unicode__(self):
        return unicode(self.object)
    def get_absolute_url(self):
        return self.object.get_absolute_url()

      

+3


source


Your code seems to be correct. I would keep the post and comment on the blog . I'm not saying this is the Django way, but the models are close enough to be in the same application.

How to split a project

I would detach the application if:

  • I am planning to create it. (and try a loose connection)
  • (for large projects) It consists of the main project section.

On the other hand; having a lot of small apps (like one model and two views app) is difficult to read and maintain IMHO.

How apps should interact

It depends on the type of project and the type of application. For example, if an application is implicitly dependent on another (ie, not shared), then importing and using links from the other application is acceptable. In this case, the second application can be installed separately, but the first requires the second.

If you want to make an application very reusable and versatile, such as a commenting application, you may need to integrate some installation mechanisms. Maybe some new settings or additional url config or special directive / method for your models ... django.contrib.admin

is a good example for this.

Applications should not interoperate unless required. Developing applications to avoid unnecessary communication is very helpful. This improves the flexibility of your application and makes it more usable (but possibly with higher integration costs).

+2


source







All Articles