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

[Bug] Exception(de)serializing models with ForeignKeys when loaded outside of 'mount' #732

Open
2 tasks done
s1liconcow opened this issue Sep 7, 2024 · 1 comment
Open
2 tasks done
Labels
bug Something isn't working

Comments

@s1liconcow
Copy link

Bug Description

I'm trying to make a view where the user can select a model and edit it. If I load the model in mount(), this works as expected. However if I try to load the model in another method, it doesn't seem to be able to deserialize it when the user saves (or does anything):

Internal Server Error: /unicorn/message/test
Traceback (most recent call last):
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/decorators.py", line 20, in timed
    result = func(*args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/__init__.py", line 49, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/views/decorators/http.py", line 64, in inner
    return func(request, *args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/__init__.py", line 556, in message
    json_result = _handle_component_request(request, component_request)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/__init__.py", line 409, in _handle_component_request
    return _process_component_request(request, component_request)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/__init__.py", line 105, in _process_component_request
    set_property_from_data(component, property_name, property_value)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/decorators.py", line 20, in timed
    result = func(*args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/utils.py", line 45, in set_property_from_data
    set_property_from_data(field, key, key_value)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/decorators.py", line 20, in timed
    result = func(*args, **kwargs)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django_unicorn/views/utils.py", line 70, in set_property_from_data
    setattr(component_or_field, name, value)
  File "/home/david/projects/my_frontend/venv/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 287, in __set__
    raise ValueError(
ValueError: Cannot assign "1": "Resource.type" must be a "ResourceType" instance.

Expected behaviour

Can use a model loaded outside of 'mount'.

Screenshots / Screenrecords

see below

Steps to reproduce

Example repro

from django_unicorn.components import UnicornView, QuerySetType
from frontend.models import Resource, ResourceType

class TestView(UnicornView):
    resource: Resource = None
    resource_types: QuerySetType[ResourceType] = None

    def mount(self):
        company = self.request.user.userprofile.company
        self.resource_types = ResourceType.objects.filter(company=company)
    
    def load(self):
        self.resource = Resource.objects.get(id=1)

    def save(self):
        self.resource.save()

The view doesn't really matter but:


{% load unicorn %}
<html>
<head>
        {% unicorn_scripts %}
</head>
<div unicorn:view>
    <button class="btn" unicorn:click="load">load</button>
    <div class="form-control mb-4">
        <input unicorn:model.defer="resource.name"></input>
        {{ resource.name }}
        <label for="edit_resource_type" class="label">
            <span class="label-text">Resource Type:</span>
        </label>
        <select id="edit_resource_type" id="resource" unicorn:model.defer="resource.type" required
            class="select select-bordered w-full">
            <option value="">Select a type</option>
            {% for type in resource_types %}
            <option value="{{ type.pk }}">{{ type.name }}</option>
            {% endfor %}
        </select>
    </div>
    <button class="btn" unicorn:click="save">save</button>
</div>
</html>

Clicking 'save' will cause it to throw the above exception. The Resource.type is a ForeignKey to ResourceType.

This, however, works:

from django_unicorn.components import UnicornView, QuerySetType
from frontend.models import Resource, ResourceType

class TestView(UnicornView):
    resource: Resource = None
    resource_types: QuerySetType[ResourceType] = None

    def mount(self):
        company = self.request.user.userprofile.company
        self.resource_types = ResourceType.objects.filter(company=company)
        self.resource = Resource.objects.get(id=1)

    def save(self):
        self.resource.save()

What browsers are you seeing the problem on?

Chrome

👀 Have you checked for similar open issues?

  • I checked and didn't find similar issue

Code of Conduct

  • I agree to follow this project's Code of Conduct

Are you willing to work on this issue ?

Yes I am willing to submit a PR!

@s1liconcow s1liconcow added the bug Something isn't working label Sep 7, 2024
@s1liconcow
Copy link
Author

I haven't quite figured out why this is broken but fwiw it seems you can 'hack' this to work with:

from django_unicorn.components import UnicornView, QuerySetType
from frontend.models import Resource, ResourceType

class TestView(UnicornView):
    resource: Resource = None
    resources: QuerySetType[Resource] = None

    def mount(self):
        self.resources = Resource.objects.all()
        self.resource = self.resources[0]
    
    def load(self):
        self.resource = self.resources[1]
    
    def save(self):
        print(self.resource.name)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant