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

Issue with validation error message when posting nested objects. #1663

Open
merabtenei opened this issue Sep 2, 2023 · 0 comments
Open

Issue with validation error message when posting nested objects. #1663

merabtenei opened this issue Sep 2, 2023 · 0 comments

Comments

@merabtenei
Copy link

merabtenei commented Sep 2, 2023

Let's take a minimal example to reproduce this use case :

#Models
class Game(models.Model):
    name = models.CharField(max_length=60)

class Player(models.Model):
    name = models.CharField(max_length=60)

class PlayerGame(models.Model):
    player = models.ForeignKey(Player, on_delete=models.CASCADE)
    game = models.ForeignKey(Game, on_delete=models.CASCADE)
    score = models.IntegerField()
#Resources
from tastypie import fields
from tastypie.resources import ModelResource
from tastypie.validation import FormValidation
from .models import Game, Player, PlayerGame
from django.forms import ModelForm
from tastypie.authorization import Authorization

def get_model_form(Model):
    class GenericModelForm(ModelForm):
        class Meta:
            model = Model
            fields = '__all__'
    return GenericModelForm

class PlayerResource(ModelResource):
    playergame_set = fields.ToManyField('games.views.PlayerGameResource', 'playergame_set', full=False, null=True, blank=True) 
    class Meta:
        queryset = Player.objects.all()
        resource_name = 'players'
        authorization = Authorization()
        always_return_data = True
        validation = FormValidation(form_class=get_model_form(Player))

class GameResource(ModelResource):
    class Meta:
        queryset = Game.objects.all()
        resource_name = 'games'
        authorization = Authorization()
        always_return_data = True
        validation = FormValidation(form_class=get_model_form(Game))

class PlayerGameResource(ModelResource):
    player = fields.ForeignKey(PlayerResource, 'player', full=True)
    game = fields.ForeignKey(GameResource, 'game', full=True)
    
    class Meta:
        queryset = PlayerGame.objects.all()
        resource_name = 'playergames'
        authorization = Authorization()
        always_return_data = True
        validation = FormValidation(form_class=get_model_form(PlayerGame))

We want to insert into api/players the following data :

{
	"playergame_set": [
		{
			"player": {"id": 3},
			"game": { "id":1 },
			"score": 100
		}
	],
	"name": "player 1"
}

This works fine and gives the expected result, but now let's see what happens if we remove some required fields in the nested object list.
For Example in this case :

{
	"playergame_set": [
		{
			"player": {"id": 3},
			"score": 90
		}
	],
	"name": "player 2"
}

We get an error message :

"error": "The 'game' field has no data and doesn't allow a default or null value."

And when removing the "score" required field we get something different :

{
	"playergames": {
		"score": [
			"This field is required."
		]
	}
}

I think this feedback lacks some information to enable any UI to correctly inform the end user were the problem is.
What we should get IMO is something like this :

{
    playergame_set: [
        { "score": [ "This field is required." ] },
        { "game": [ "This field is required." ] },
        { "game": [ "This field is required." ], "score": [ "This field is required." ] },
    ]
}

We need to get a feed back for each row we want to insert and the "key" should be the name of field as we named it in the resource fields. This would enable the front end UI to automatically map error messages to form inputs (displaying each error message exactly under the right input).
I really need some orientations on which parts of the Resource class should I change to get this kind of behavior.

Thank you for taking the time to read this.

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

1 participant