2
votes

Im a .net developer used to work with asp.net mvc framework and Im trying to introduce myself to the python world, specifically trying to code some websites using django, but Im having a hard time figuring out django's structure.

In asp.net mvc, I use asp.net mvc framework just as a presentation layer, my business logic and my data layer is independant. This is the basic structure of all my asp.net mvc sites:

enter image description here

The website is an asp.net mvc project, while the business logic and the datatypes projects are class libraries (dlls). In the business logic project, I use an entity framework model (with all the classes it generates) and I create some classes that I call "Managers" that contains the core logic of the system. For example if the webiste is for a blog website, the "UsersMgr" would contain the following operations "RegisterUser, GetUser, ConfirmUserAccount" and the "PostsMgr" would contain the operations "AddPost, RemovePost, EditPost, AddComentToPost, etc".

The idea in this approach is that the website is just a presentation layer, which uses the business logic, but its not tightly coupled to it. I usually add an "Admin Console" (another asp.net mvc website for the administrators), "Reports for some partner" (for example imagine that the blog has advertisement and we give the partners a login so they can update their ads and see reports on how many times the ad was shown, etc), a "rest api" so that if I want to create a mobile app I can expose the business logic through a rest API, crons to run maintainance tasks or reports to be sent my email at the end of each day, etc.

On my .net projects with the previous architecture, adding those new things looks like this:

enter image description here

Basically all those new added items are "consumers" of the business logic.

Im having a hard time figuring out how to achieve something like this with django, because the web apps seem really tightly coupled with their models, which are mappings to the db tables. So where should I put the business logic if I want to reuse it later in a non django website?

And about the django apps, I read all over the place that its good to split the website in django apps, but how do you do it when usually the concepts are coupled. For example, a blog might have users, posts, comments, tags, etc. My problem is that everything is linked together, the posts belong to a user, the tags and the comments are linked to a post. What do you do with this relationships?

I would really appreciate if someone could help me with this, I did some python scripts for my raspberry pi and it looks like an awesome language, but Im having a hard time with django. There has to be something that Im missing...

Thanks!

2

2 Answers

3
votes

Views and Models

Models are the equivalent of your Data Types component. Views are the equivalent of the website part, and will typically contain the code that your "Managers" would contain.

I assume that "business logic" refers to things like "only users that meet certain conditions may comment on a post". Then your right in saying that putting that directly in a view isn't great, because if your users can access the system in another way (say a locally running command line utility) then you would need to repeat that logic there.

The answer is to add the business logic to the model itself, by adding custom functions to the model class that are the equivalent of your Manager's "GetX", "GetY", and adding stuff like "can this user do this" logic to the save hooks of the model.

There is nothing to stop you from creating a Manager layer between your views and your models, something like:

models.py:

class Post(models.Model):
    ...

class Comment(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    text = models.CharField(...)

managers.py:

class PostManager(object):
    @staticmethod
    def getPost(id):
        return Post.object.get(pk=id)

    @staticmethod
    def addComment(post, comment_text, user):
        comment = Comment(post=post, user=user, text=comment_text)
        # check stuff
        comment.save()
    ...

views.py:

def add_comment(request, post_id):
    ...
    PostManager.addComment(post=PostManager.getPost(post_id),
                           user=request.user,
                           request.POST['text'])
    ...

But this has several drawbacks:

  • The API of the model instance is still available to bypass such checks
  • You're losing out on the expressive power of the model API
  • It's somewhat overly verbose

The principle advantage would be that you can seamlessly swap out the whole Django models thing for an entirely different ORM. But if this is not something your likely to do, then I would not go down this road.

Django apps

It is a good idea to split things in to apps. The apps should be partitioned down functional lines, separating the different things that your overall project does.

In your example (blogs, posts, comments, users), you've really got two apps. The one that deals with users (logging in/out, registration, password resets, etc), and one that deals with blogging (posting, commenting, etc.).

It is not a bad thing that the blog app depends upon the user app, it makes sense to leverage that existing functionality in the blog app that the user app provides.

Down the line, this allows for easy reuse (you might have another project with users, but not a blog).

3
votes

I've seen a lot of developers with the same doubts about Django. The thing is, Django's approach to MVC is a little different. Django ORM abstracts any connection with the database itself and make models take care of the business logic. Even if Django let's you take care of your own database structure, use triggers, processes and whatnot, Django can make all those things at application level as well, leaving your project absolutely database-agnostic.

Django also promotes the use of fat models and managers. Managers in Django can take the place of MVC's controllers at some point, because their job is to deal with collections of model instances. You can extend a model manager to accommodate the instructions you're used to, though.

Database independence is huge benefit for some, it also means that your data model is tied to the Django project, and it would be of very little use for using it in other projects, but hey, that's what interfaces are for!

The Admin application is built-in in Django and it's really easy to customize to your needs.

Talking about interfaces, Django's views are just that, an interface. It doesn't tell you how you should present your data. Django has a very powerful template framework but it's really optional. If you're trying to implement a REST interface, Django REST Framework or Django Tastypie can have the job done in a few hours because all your business logic is already defined in a common language, and those apps all benefit from that and expose that logic beautifully.

And now to the apps part. Think of your project in terms of features: Users could be one, Registration should be another, Blogging, Comments, Tag Management. Users can have the user, profile and group models, registration doesn't need models, Blogging has the post and category models, and tag management deals with the tag model.

Applications are just well-packed functionalities, they have models, views, urls, etc., and it's OK to make them work together. You can have relationships between applications (blog post has many tags). Of course, if you delete the Tag application maybe Blogging would break now, so think ahead of those things (maybe it's the tag that has many blog posts).

If you have any more questions, ask me in the comments and I'll try to be as clear as possible.