-
-
Notifications
You must be signed in to change notification settings - Fork 119
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
feature request: make self.request
available within javascript_exclude
class properties
#650
Comments
Hey, that's pretty weird and unexpected. I'll try to take a look and see if it's a straight-forward fix over the next couple of days. |
awesome, thank you for taking a look 😄 |
Sorry, this took longer than I was expecting because I'm having trouble replicating this. #653 has an example that is basically what you were trying. It looks to me like |
This is odd because that exact same view doesn't work in my setup. The main difference with my server is that I use extra notesTo help debug, I tried adding the following print statements to
# method is identical besides print statements
if isinstance(self.Meta.javascript_exclude, Sequence):
print(f"frontend_context_variables: {frontend_context_variables}")
print(f"Attempt property access: {self.user}")
# ... And the output was...
So for some reason the property works as expect (it prints This leads to the following error + traceback: Internal Server Error: /apps/spotfire/debugging/
Traceback (most recent call last):
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django\core\handlers\base.py", line 220, in _get_response
response = response.render()
^^^^^^^^^^^^^^^^^
File "<decorator-gen-20>", line 2, in render
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django_unicorn\decorators.py", line 20, in timed
result = func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django_unicorn\components\unicorn_template_response.py", line 138, in render
frontend_context_variables = self.component.get_frontend_context_variables()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<decorator-gen-26>", line 2, in get_frontend_context_variables
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django_unicorn\decorators.py", line 20, in timed
result = func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nxj625\AppData\Local\anaconda3\envs\simmate_dev\Lib\site-packages\django_unicorn\components\unicorn_view.py", line 452, in get_frontend_context_variables
raise serializer.InvalidFieldNameError(
django_unicorn.serializer.InvalidFieldNameError: Cannot resolve 'user'. |
I'm still getting the error in a clean setup. So I was wrong in my previous comment about I used our basic view inside an otherwise empty django setup:
When you read through those files, you'll see it's everything from the default "start project" command in django, plus the view in question. And once you start the server, you can see the error at |
Thanks for the sample code and all of the details. So, I think there are a few things going on here. I assume you saw this warning and were trying to put a https://www.django-unicorn.com/docs/views/?highlight=property#javascript-exclude is only applicable for attributes, not methods or properties. As far as I can tell, properties are not callable from the frontend at all. I tested with the following changes to You can see that Hopefully, that all makes sense. Let me know if there are documentation changes I can make (other than the blatant one I mentioned above) that could make this more clear. |
I've been using properties a ton in my views, and they seem to work fine as long as I don't try to use from django_unicorn.components import UnicornView
class Debug(UnicornView):
template_name = "polls/index.html"
class Meta:
javascript_exclude = ()
@property
def basic_property(self):
return 12345
@property
def user_property(self):
return str(self.request.user) {% load unicorn %}
<html>
<head>
{% unicorn_scripts %}
</head>
<body>
{% csrf_token %}
<div unicorn:view>
Basic Property: {{ basic_property }}
<br>
User Property: {{ user_property }}
</div>
</body>
</html> You can see So I assumed attributes and properties behaved the same across all
Not exactly 😅. I'm putting properties in
I used from functools import cached_property
class Example(UnicornView):
class Meta:
javascript_exclude = ("user_chemicals",)
@cached_property
def user_chemicals(self) -> list:
"""
a list of ~100-300 chemical names that are assigned
to this user and/or the user's team
"""
user = self.request.user
chemicals = user.assigned_chemicals.filter(....).all()
return chemicals
# then there are a series of normal methods/attributes that
# handle how `user_chemicals` are used within an
# interactive form. For example, one of these chemicals
# can be selected from a dropdown menu, and set to
# an attribute:
selected_chemical_id = None So I'm using |
also I'm sorry for my long comments! Hopefully they aren't too much... I really appreciate you taking the time to read through and help me out 😊 |
Oh my gosh, ok. 🤦 Well, at least that fits into what I would have expected! Sorry for that red herring around properties -- it's been a while since I've used a property in a component. Thanks for being patient and explaining the situation. I have a few potential leads now and I'm going to see if I can figure out what is going on. |
fyi - I have a workaround for this issue. It requires a couple lines of extra boilerplate, but it gets the job done: from functools import cached_property
class Example(UnicornView):
class Meta:
javascript_exclude = ("user_chemicals",)
user_chemicals: list = None
def mount(self):
self.user_chemicals = self.get_user_chemicals()
def get_user_chemicals(self) -> list:
user = self.request.user
chemicals = user.assigned_chemicals.filter(....).all()
return chemicals So instead of using |
When I set an attribute dynamically via a
@property
attribute and also add it tojavascript_exclude
, therequest
is no longer accessible fromself
.Here's the minimal amount of code to reproduce:
This is a silly example (since
request.user.id
is already accessible in the template). In a real-world example, I would use therequest.user
within a property to grab things like user settings and/or database objects related to user + add extra python logic.Is there a way to implement this?
The text was updated successfully, but these errors were encountered: