首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Django管理中为每个模型添加自定义字段

在Django管理中为每个模型添加自定义字段
EN

Stack Overflow用户
提问于 2019-09-08 00:14:36
回答 1查看 759关注 0票数 1

我正在我的个人网站上工作,并想同时处理前端和数据库翻译(即拥有2-3种语言的所有内容)。虽然已经有很多第三方应用程序来处理数据库中的翻译,但我认为构建自己的应用程序既有趣又有趣。

我在最后一步。到目前为止,一切都很顺利。下面简要介绍一下它是如何工作的(跳过几件事情):

  • 我在django项目中有一个“翻译”应用程序
  • 它提供了几个不同的表,最显著的是:
    • 语文:现有语文一览表
    • 项目:相当于说“这是‘作业’模型实例33的‘名称’字段”
    • 翻译:语言和项目之间的ManyToMany。基本上是一个给定项目的所有翻译。

  • 这个应用程序提供了一个名为“翻译模型”的抽象模型。
  • 您的常规应用程序中的每个模型都必须继承该模型中的字段。
  • 通过信号和FK关系,应用程序然后处理项目和翻译表中条目的创建和删除(自动)。

好的,假设我们有一个“作业”模型,其中有两个必须翻译的字段:、title、和现在,每当我在作业中创建一个新条目时,下面是自动发生的情况:

  • 在Item中创建了2个新条目:
    • 作业n°X,名称
    • 作业n°X,描述

  • 在翻译中创建了4个条目:
    • 作业n°X,名称,法语
    • 作业n°X,描述,法语
    • 作业n°X,名称,英文
    • 作业n°X,描述英语

我的问题如下:

  • 我有许多表,如“作业”,这些表将触发项目中的新条目,然后再进行翻译
  • 这些表对项目表都有ForeignKey,但对这些表没有ForeignKey (因为同一列存储来自不同表的数据)。

我想做的是:

  • 在管理上,当我在像“作业”这样的表上时,我想看到并直接更新它的翻译文本(Translation.text)。这意味着看到上面提到的四个不同的“翻译”条目。我已经有了一个获得翻译实例的函数,现在更多的是在管理程序中显示和编辑它们。
  • 与其手动重写每个模型/管理表单,是否有一种方法可以在全局应用此更改。

我的想法是“通过添加一个专门用于翻译的新区域来覆盖一般的change_form.html,该区域获取与实例相关的所有翻译条目”(只有在此实例受翻译约束的情况下)。但不知道该怎么做。

(请注意,我已经自动检测到所有需要翻译的模型,并且可以很容易地获得它们的特定字段)

如能提供任何帮助,将不胜感激:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-25 20:51:19

对于遇到这个话题的人,我已经解决了这个问题,并发布了我自己的数据库翻译应用程序。代码是完全开放源代码的,可以在这里获得:https://pypi.org/project/django-database-translation/

至于我在最初的文章中提到的问题,我成功地应用了以下逻辑:

  • 我创建了一个ModelForm,它动态地为一个项生成“要翻译的字段”。
  • 我创建了一个ModelAdmin,它使用此表单并生成与上面的表单相同的字段名。
  • 因此,如果我在管理中继续我的“工作”项,我可以访问它的所有翻译,并可以从这个页面直接更改它们。

以下是这些片段,也可在translation上使用

代码语言:javascript
复制
class DynamicTranslationForm(forms.ModelForm):
    """
    Form to use in a ModelAdmin for any model that has fields to translate.
    It will allow you to display and edit the Translation instances linked to the object.
    Since fields are dynamically generated, you must override the get_fieldsets method in the admin (or else they won't show)
    The "TranslatedAdmin" ModelAdmin natively use this form.
    """

    # ----------------------------------------
    # Core Methods
    # ----------------------------------------
    def __init__(self, *args, **kwargs):
        """Overridden method to dynamically add a new field for each Translation linked with our object"""
        super(DynamicTranslationForm, self).__init__(*args, **kwargs)
        if self.instance.pk:
            self.set_translation_info()
            for translation in self.translations:
                self.fields[translation["fieldname"]] = translation["field"]
                self.initial[translation["fieldname"]] = translation["instance"].text

    def save(self, commit=True):
        """Overridden method to save the updated Translation texts"""
        if self.instance.pk:
            for translation in self.translations:
                obj = translation["instance"]
                fieldname = translation["fieldname"]
                value = self.cleaned_data[fieldname]
                obj.text = value
                obj.save()
        return super(DynamicTranslationForm, self).save(commit=commit)

    # ----------------------------------------
    # Custom Methods
    # ----------------------------------------
    def set_translation_info(self):
        """
        Finds all the Translation instances linked to our object, and stores their info in an attribute
        The attribute is a list of dict, each dict containing the information of one translation
        """
        obj = self.instance
        information = []
        translations = obj.get_translations()
        for translation in translations:
            fieldname = create_translation_fieldname(translation)
            information.append({
                "instance": translation,
                "fieldname": fieldname,
                "field": forms.CharField(required=False, widget=forms.Textarea)
            })
        self.translations = information
代码语言:javascript
复制
# ADMIN.PY
class TranslatedAdmin(admin.ModelAdmin):
    """
    ModelAdmin to use as parent for any model that has fields to translate
    It comes with the "DynamicTranslationForm" and custom methods to display its fields
    """

    # ----------------------------------------
    # Config
    # ----------------------------------------
    form = DynamicTranslationForm

    # ----------------------------------------
    # Detail View
    # ----------------------------------------
    fieldsets = []

    # ----------------------------------------
    # Custom Methods
    # ----------------------------------------
    def get_form(self, request, obj=None, **kwargs):
        """Required for get_fieldsets"""
        kwargs['fields'] = flatten_fieldsets(self.fieldsets)
        return super().get_form(request, obj, **kwargs)

    def get_fieldsets(self, request, obj=None):
        """
        Allows us to display the field dynamically created by "DynamicTranslationForm"
        The fieldnames in "DynamicTranslationForm" and this function must be identical
        In other words:
        - "DynamicTranslationForm" creates the fields
        - This function adds fields with the same name to the fieldsets
        - As a result, the fields now appear on the form
        """
        fieldsets = self.fieldsets.copy()
        # Get current Item
        url = request.build_absolute_uri("?")
        if url.endswith("/change/"):
            url = url[:-8]
            object_id = url.split("/")[-1]
            obj = self.model.objects.get(pk=object_id)
            # Create a field for each translation associated with our object
            fields = []
            translations = obj.get_translations()
            for translation in translations:
                fieldname = create_translation_fieldname(translation)
                fields.append(fieldname)
            # Add a fieldset with our fields
            fieldsets.append(['TRANSLATIONS', {'fields': fields}])
        return fieldsets
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57838295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档