首页 > 解决方案 > Django - 从模型中自动化 CRUD(DRY 方法)?

问题描述

我是 Django 新手,但不是开发新手。

我需要制作一个用户可以在其中执行 CRUD 操作(创建、读取、更新、删除)的应用程序。此功能应适用于所有模型,创建和更新的字段将从模型属性自动生成。

我所描述的几乎是管理页面附带的功能。但是,我想在我自己的应用程序中使用它,而不是使用管理应用程序。

例如,假设我们有AuthorBook模型:

( models.py)

from django.db import models

class Author(models.Model):
    first_name = models.CharField(max_length=60)
    last_name = models.CharField(max_length=60)

    def __str__(self):
        return self.last_name

class Book(models.Model):
    title = models.CharField(max_length=60)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

我想以上信息(模型)对于 CRUD 操作来说已经足够了,不需要为每个模型重复相同逻辑的代码。我的目标是管理页面中的功能,您所要做的就是注册您的模型。

我知道ModelFormGeneric Views,但是虽然它们有助于避免对表单字段进行硬编码,但我还没有找到一种非重复编码方法。我想避免以下方法,其中每个模型都复制相同的代码:

( forms.py)

from django import forms
from todo.models import Author, Book

class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        fields = '__all__'

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = '__all__'

( views.py)

from django.views.generic import CreateView
from.forms import AuthorForm, BookForm
from.models import Author, Book

class AuthorCreateView(CreateView):
    model = Author
    form_class = AuthorForm
    ...

class BookCreateView(CreateView):
    model = Book
    form_class = BookForm
    ...

那么,DRY CRUD 解决方案的最佳方法是什么(如在管理页面中)?我是否缺少任何 Django 功能?

标签: djangocruddry

解决方案


将我的解释放在评论中,您会得到如下信息:

from django.views import generic
from myapp.apps import MyAppConfig
from django.forms import modelform_factory


urlpatterns = []
for model in MyAppConfig.get_models():
    create_url = path(
        f"{model.__class___.__name__.lower()}/create",
        generic.CreateView.as_view(
            form_class=modelform_factory(model=model, fields='__all__'),
            template_name=f"{model._meta.app_label}/create.html",
            model=model
        ),
   ),
   list_url = path(
        f"{model.__class__.__name__.lower()}/",
        generic.ListView.as_view(
            template_name=f"{model._meta.app_label}/list.html",
            model=model
        ),
    ),
   ...
   urlpatterns.extend([create_url, list_url, read_url, update_url, delete_url])

所以原则是使用通用视图和模型表单工厂,生成标准的 crud 视图,从模型名称派生路径名,并在应用程序中为每个视图使用一个模板(从模型的 app_label 派生)。

使用我之前链接的文档,您应该能够将事情拼凑起来。


推荐阅读