简体   繁体   English

Using Django, should I implement two different url mapping logics in my REST API and web application, and how?

[英]Using Django, should I implement two different url mapping logics in my REST API and web application, and how?

I have a Book model an instance of which several instances of a Chapter model can be linked through Foreign Key:我有一Book model 一个实例,其中一个Chapter model 的几个实例可以通过外键链接:

class Book(models.Model):
    pass

class Chapter(models.Model):
    book = models.ForeignKey(to=Book, ...)
    
    class Meta:
        order_with_respect_to = "book"

I decided to use Django both for the RESTful API, using Django Rest Framework, and for the web application, using Django Template. I decided to use Django both for the RESTful API, using Django Rest Framework, and for the web application, using Django Template. I want them separate as the way should be open for another potential application to consume the API.我希望它们分开,因为应该为另一个潜在的应用程序使用 API 打开方式。

For several reasons including administration purposes, the API calls for a url mapping logic of this kind:出于包括管理目的在内的多种原因,API 需要这种类型的 url 映射逻辑:

mylibrary.org/api/books/
mylibrary.org/api/books/<book_id>/
mylibrary.org/api/chapters/
mylibrary.org/api/chapters/<chapter_id>/

For my web application, however, I would like the user to access the books and their contents through this url mapping logic:但是,对于我的 web 应用程序,我希望用户通过此 url 映射逻辑访问书籍及其内容:

mylibrary.org/books/
mylibrary.org/books/<book_id>-esthetic-slug/
mylibrary.org/books/<book_id>-esthetic-slug/chapter_<chapter_order>/

The idea is the router to fetch the book from the <book_id>, whatever the slug might be, and the chapter according to its order and not its ID.这个想法是路由器从 <book_id> 中获取书籍,无论 slug 是什么,以及根据其顺序而不是 ID 的章节。

Now I need some advice if this is desirable at all or if I am bound to encounter obstacles.现在我需要一些建议,如果这是可取的,或者我一定会遇到障碍。 For example, how and where should the web app's <book_id>/<chapter_order> be "translated" into the API's <chapter_id>?例如,web 应用程序的 <book_id>/<chapter_order> 应如何以及在何处“翻译”为 API 的 <chapter_id>? Or if I want the web app's list of books to offer automatically generated slugged links to the books, should it be done at the API or the web app level?或者,如果我希望 web 应用程序的图书列表提供自动生成的图书链接,应该在 API 还是 web 应用程序级别完成?

I'm pretty new to Django / DRF and web development in general.一般来说,我对 Django / DRF 和 web 开发很陌生。

The double URLs are not a problem at all.双 URL 根本不是问题。 It is used whenever the program renders views and has an API (perhaps for a mobile app) as well.每当程序呈现视图并具有 API(可能用于移动应用程序)时,都会使用它。 What I usually do is have the id field be in the URL of the 'web' pages too, it is simpler for me to keep track of.我通常做的是将id字段也放在“web”页面的 URL 中,这对我来说更容易跟踪。 However if you want to have a 'nice' slug in the URL, try this:但是,如果您想在 URL 中有一个“好”的弹头,试试这个:

"""
models.py
"""

import uuid

from django.db import models


class Book(models.Model):
    id = models.UUIDField(primary_key=True, null=False, editable=False, default=uuid.uuid4)
    slug = models.SlugField(max_length=50)

class Chapter(models.Model):
    id = models.UUIDField(primary_key=True, null=False, editable=False, default=uuid.uuid4)
    book = models.ForeignKey(to=Book, ...)
    sort = models.PositiveIntegerField()
    
    class Meta:
        order_with_respect_to = "book"
        unique_together = [("book", "sort"), ]  # so that there is never two chapters with the same number
"""
urls.py
"""

from django.urls import path

from . import apiviews, views

urlpatterns = [
    # 'web' URLs
    path("books/", views.books, "book_list"),  # mylibrary.org/books/
    path("books/<str:book_slug>", views.book, "book"),  # mylibrary.org/books/harry-potter-and-the-prisoner-of-azkaban
    path("books/<str:book_slug>/chapter_<int:chapter>", views.chapter, "chapter"),  # mylibrary.org/books/harry-potter-and-the-prisoner-of-azkaban/chapter_2
    # API URLs
    path("api/books/", apiviews.books, "api_book_list"),  # mylibrary.org/api/books/
    path("api/books/<uuid:id>", apiviews.book, "api_book"),  # mylibrary.org/api/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459
    path("api/chapters/", apiviews.chapters, "api_chapters"),  # mylibrary.org/api/chapters/
    path("api/chapters/<uuid:id>", apiviews.chapter, "api_chapter"),  # mylibrary.org/api/chapters/c76a89ae-ad73-4752-991c-8a82e47d3307
]
"""
views.py
"""

from .models import Book, Chapter


def books(request):
    book_list = Book.objects.all()


def book(request, book_slug)
    try:
        book = Book.objects.get(slug=book_slug)
    except Book.DoesNotExist:
        pass


def chapter(request, book_slug, chapter)
    try:
        book = Book.objects.get(slug=book_slug)
        chapter = book.chapter_set.get(sort=chapter)
    except Book.DoesNotExist:
        pass
    except Chapter.DoesNotExist:
        pass
"""
apiviews.py
"""

from .models import Book, Chapter


def books(request):
    book_list = Book.objects.all()


def book(request, id)
    try:
        book = Book.objects.get(id=id)
    except Book.DoesNotExist:
        pass


def chapters(request):
    chapter_list = Chapter.objects.all()


def chapter(request, id)
    try:
        chapter = Chapter.objects.get(id=id)
    except Chapter.DoesNotExist:
        pass

These files reflect how you suggested the URLs.这些文件反映了您建议 URL 的方式。 I personally (and I don't say that is the correct way) would have the API views set up like this:我个人(我并不是说这是正确的方法)会像这样设置 API 视图:

mylibrary.org/books/
mylibrary.org/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459
mylibrary.org/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459/chapters/
mylibrary.org/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459/chapters/3
# and then for example:
mylibrary.org/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459/comments/
mylibrary.org/books/b21a0af6-4e6c-4c67-b44d-50f8b52cd459/comments/295

I find this structure more comprehensive but I can't see any pros or cons against your version.我发现这种结构更全面,但我看不出您的版本有任何优点或缺点。 Both work just as fine and there is a good reasoning behind both of them.两者都工作得很好,而且它们背后都有很好的理由。 One being "API is just a way to access the database objects and so I should be able to pull an arbitrary chapter if I know the ID" , the other "I have books and books have chapters, so a chapter is a sub-thing of books" .一个是“API 只是访问数据库对象的一种方式,所以如果我知道 ID,我应该能够拉出任意章节” ,另一个是“我有书,书有章节,所以章节是子事物书”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM