Coder Social home page Coder Social logo

sibyx / django_api_forms Goto Github PK

View Code? Open in Web Editor NEW
20.0 5.0 13.0 1.16 MB

Declarative Django request validation for RESTful APIs

Home Page: https://sibyx.github.io/django_api_forms/

License: MIT License

Python 100.00%
django django-validators json rest http django-forms hacktoberfest

django_api_forms's Issues

RRuleField

It will be nice to have RRuleField which will normalize from RRULE to dateutil.rrule object.

Field should be available only if dateutil is installed (it's not required dependency).

Placeholders not filled

Placeholders are not filled in error message.

{
  "validation_errors": [
    {
      "code": "password_too_short",
      "message": "This password is too short. It must contain at least %(min_length)d characters.",
      "path": [
        "new_password"
      ]
    }
  ]
}

Error in `clean_` methon

When you check values in clean_ method in Form, sometimes it returns None value.

class NewAlbumForm(Form):
    album_id = forms.ModelChoiceField(queryset=Album.objects.all(), required=True)
    scheduled_at = fields.DateField(required=True)

    def clean_album_id(self):
        if self.cleaned_data.get('album_id').type in [Album.AlbumType.CD]:
        # if self.cleaned_data.get('album_id').type != Album.AlbumType.CD:
            self.add_error(
                'album_id',
                ValidationError('You did not select CD', code='not-cd')
            )
        else:
            return self.cleaned_data['album_id']

Create EnumField in Form::fill()

Form::fill() method fills object with enum string value instead of enum object instance. Basically you have to do something like this which is pretty ugly:

widget = ReportWidget()
form.fill(widget)
widget.type = ReportWidgetType(widget.type)
widget.save()

Empty FormFieldList validation

When I set FormFieldList required to true, empty list will raise an required exception.

I think that required validation should be assigned only to the key (if we think about json as a dictionary) and not to the value.

Maybe adding a new attribute blank or empty to the List type forms, to make control above values?

Unique field parameter

We need to check unique field like in django forms:


def clean_email(self):
        email = self.cleaned_data['email']
        if User.objects.filter(email=email).exists():
            raise ValidationError("Email already exists")
        return email

Use `Poetry` for install, build and publish instead of `setuptools` and `twine`.

Is your feature request related to a problem? Please describe.

I have noticed that this project has an unnecessary setup.py file since it is already using poetry. Therefore, metadata that exists in setup.py should be moved into pyproject.toml.

Describe the solution you'd like

Given the above info, this requires changing some CIs like publish.yml to use poetry based github actions like publish-python-poetry-package. Also, some commands to install, build and publish should be poetry based.

Describe alternatives you've considered
Not available.

Additional context
For security reasons, Pypi suggests using API tokens to authenticate instead of a username and password. That's pretty much it. What do you think? Also, I would like to work on this issue if possible.

Empty cleaned data in clean method

I would like to check, if data are valid in base_64 encoded message. This process is made in clean_items_base64 method. But when this method is processed, now method clean have cleaned_data as empty dict.

If I remove whole clean_items_base64 method, clean works and cleaned_data are there.

We need to write test, which duplicate this issue. After that, we need to find reason, fix it and make that test to run successfully.

Example:

class Sign(Form):
    class QrCodeForm(Form):
        items_base64 = forms.CharField(required=True)

        def clean_items_base64(self):
            items_base64 = self.cleaned_data.get('items_base64')
            decoded_items_base64 = base64.b64decode(items_base64.encode()).decode()
            items = json.loads(decoded_items_base64)

            for item in items:
                amount = item.get('amount', 0)
                item_category_id = item.get('item_category_id')

                if not amount or amount == 0:
                    self.add_error(
                        ('items_base64',),
                        ValidationError(
                            _("Amount can't be zero"),
                            code='office-not-price-list'
                        )
                    )
                if not item_category_id:
                    self.add_error(
                        ('items_base64',),
                        ValidationError(
                            _('Item category identification is required'),
                            code='office-not-price-list'
                        )
                    )

            return items_base64

        payload = FormField(form=QrCodeForm, required=True)

class Synchronize(Form):
    class Item(Form):
        name = forms.CharField(required=False)
        sign = FormField(form=Sign, required=True)
    plans = FormFieldList(form=Item, required=True)
    
    def clean(self):
        # Here are cleaned_data empty dict: {}
        for index, item in enumerate(self.cleaned_data.get('plans', [])):
            pass

        return self.cleaned_data

Property aliases

Is your feature request related to a problem? Please describe.

Sometimes you need to have an ability to create mapping between Form properties and keys from request.

For example, you want to map _id JSON attribute into id property of ExampleForm.

{
    "_id": 15
}
class ExampleForm(Form):
     id = fields.IntegerField()

Describe the solution you'd like

Introduce mapping property in Form object using Meta class.

class ExampleForm(Form):
    class Meta:
        # source:destination
        mapping = {
            '_id': 'id'
        }
     
     id = fields.IntegerField()

FieldList can not show internal field message errors

FieldsList does not show error message of internal fields.

contact_numbers = FieldList(field=fields.CharField(max_length=17), required=True)
"validation_errors": [
    {
      "code": "max_length",
      "message": "",
      "path": [
        "contact_numbers",
        0
      ]
    }
  ]

Updating Django Docs Links

Many of the Links in the Readme File are pointing to Django Docs for the version < 3.2, which is no longer supported. I think these links should be updated to Django Version 3.2 atleast or higher than that.

Linear validation errors

This issue has been inspired by Problem Details for HTTP APIs - RFC7807 and blog post Structuring validation errors in REST APIs written by @k3nn7.

The main idea is to simplify the validation process on the client-side by flattening errors output. To achieve such
a goal, the whole validation process have be rewritten (and luckily for us, much simplified). This will be a breaking change and will be released as 1.0.

The DetailedValidationError should be implemented which inherits from ValidationError and can keep position in lists nested forms. The form will return a linear list of errors instead of a nested dictionary.

Example request

{
  "authors": [
    {
      "name": "Bla",
      "surname": "Bla"
    },
    {
      "surname": "Hihi"
    }
  ],
  "password": "password"
}

Example validation error structure

{
  "errors": [
    {
      "path": ["authors", 1, "name"],
      "json-path": "$.authors.1.name",
      "message": "Field is required!",
      "code": "required"
    },
    {
      "path": ["password"],
      "json-path": "$.password",
      "message": "Password is too short!",
      "code": "too-short",
      "min-lenght": 10
    },
    {
      "path": ["password"],
      "json-path": "$.password",
      "message": "Password is too simple!",
      "code": "too-simple"
    },
    {
      "path": ["username"],
      "json_path": "$.username",
      "message": "Field have to be unique!",
      "code": "unique"
    }
  ]
}

Additional params in form creation

I would appreciate having the option to insert additional objects into form creation for usage in clean custom methods.

Example:

def create_from_request(cls, request, **kwargs):
    pass

form = MyForm.create_from_request(request, param1=param1, param2=param2)

class MyForm(Form):
    def clean(self):
        param1 = self.kwargs['param1']
        param2 = self.kwargs['param2']

Detailed documentation

Documentation is essential part of every project (in my opinion, it's not enough to keep full example in README file - which is starting to be quite long).

My idea is to create GitHub pages using mkdocs and mkdocs-material (like in duckql-python repository) with:

  • documentation (with motivation why we decited to create them - BooleanField is pretty interesting) for each custom field (which is not part of Django)
  • process of validation (how normalization in processed)
  • nesting forms
  • database relationships
  • fill method
  • file uploads
  • model forms
  • settings

Library name

I am not very proud of naming library django_requests_formatter because is not very accurate (To be honest, I think that name doesn't make any sense).

I am opening this issue to collect potential library names. It's much more easier to rename library in this stage of development before major release.

List of potential names:

  • django_api_forms
  • django_rest_forms

Population strategies

Is your feature request related to a problem? Please describe.

I need to override default behaviour for specific form fields in Form.fill method

Describe the solution you'd like

I would like to introduce field fill strategies, which could be overrided like this:

DJANGO_API_FORMS = {
    'FILL_STRATEGIES': {
        'django.forms.CharField': 'apps.api.forms.strategies.CharFieldStrategy',
        'django.forms.ModelMultipleChoiceField': 'django_api_forms.strategies.ModelMultipleChoiceFieldReplaceStrategy',
        'apps.api.forms.fields.LocalisationField': 'apps.api.forms.strategies.LocalisationStrategy'
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.