【问题标题】:Django - automate CRUD from models (DRY approach)?Django - 从模型中自动化 CRUD(DRY 方法)?
【发布时间】:2021-05-12 09:52:02
【问题描述】:

我是 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 功能?

【问题讨论】:

  • 您缺少modelform_factory 以及向as_view() 添加参数的能力,这些参数也可以以声明方式使用。因此,您可以从 urlpatterns 构造中实例化所有这些,使用 apps.get_models() 为模型播种。
  • 您能否通过发布示例的答案来详细说明?

标签: django crud dry


【解决方案1】:

把我的解释放在评论里,你会得到这样的:

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 派生)。

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

【讨论】:

  • 我收到一个错误:Calling modelform_factory without defining 'fields' or 'exclude' explicitly is prohibited。我尝试添加一个空的排除列表,但没有帮助。
  • 与您的模型表单相同:fields = '__all__'.
猜你喜欢
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
  • 2023-03-12
  • 2016-01-11
  • 1970-01-01
  • 2018-08-29
相关资源
最近更新 更多