Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SerializerForm class does not match documentation #20

Open
toshka opened this issue Oct 16, 2017 · 2 comments
Open

SerializerForm class does not match documentation #20

toshka opened this issue Oct 16, 2017 · 2 comments

Comments

@toshka
Copy link

toshka commented Oct 16, 2017

Here described how to create form from serializer class (MyForm). But actually this does not work because there is no fields attribute declared in Meta.
Why drf_braces.forms.serializer_form.SerializerFormOptions does not populates fields from serializer's _declared_fields? Is it feature or bug? Can I send PR to change this behavior?

@shahmitul
Copy link

@toshka correct, looks like their own example doesn't work. It is not populating any fields.

@SebCorbin
Copy link

SebCorbin commented Aug 10, 2021

For the record, it seems SerializerForm only works with basic forms (and basic serializers ?), so if you want to work with model forms, you'll need to create another base class:

from django import forms
from django.forms.models import ModelFormMetaclass
from drf_braces.forms.serializer_form import SerializerFormMeta, SerializerFormOptions


class SerializerModelFormMeta(SerializerFormMeta, ModelFormMetaclass):
    def __new__(cls, name, bases, attrs):
        try:
            parents = [b for b in bases if issubclass(b, SerializerModelForm)]
        except NameError:
            # We are defining SerializerModelForm itself
            parents = None

        meta = attrs.get('Meta', None)

        if not parents or attrs.pop('_is_base', False):
            return ModelFormMetaclass.__new__(cls, name, bases, attrs)

        attrs['_meta'] = options = SerializerFormOptions(meta, name=name)

        new_attrs = cls.get_form_fields_from_serializer(bases, options)
        # attrs should take priority in case a specific field is overwritten
        new_attrs.update(attrs)

        # transfer the fields from serializer to the ModelForm
        if getattr(options.serializer, 'Meta'):
            new_attrs['Meta'].fields = options.serializer.Meta.fields
            new_attrs['Meta'].model = options.serializer.Meta.model

        return ModelFormMetaclass.__new__(cls, name, bases, new_attrs)


class SerializerModelForm(forms.BaseModelForm, metaclass=SerializerModelFormMeta):
    _is_base = True

Which can be used after like this

from django import forms
from rest_framework import serializers
from base.models.person import Person
from base.forms import SerializerModelForm


class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = [
            'first_name',
            'last_name',
            'language',
            'birth_date',
        ]

class PersonForm(SerializerModelForm):
    class Meta:
        serializer = PersonSerializer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants