yaakovLowenstein / hx-requests

A package to facilitate the use of HTMX with Django
MIT License
55 stars 6 forks source link

Inconsistencies with Django’s Class-Based View (CBV) API #112

Open sgordon16 opened 2 months ago

sgordon16 commented 2 months ago

Description

As someone who regularly works with Django’s Class-Based Views (CBVs), I’ve found hx_requests to be confusing because it tries to follow the CBV pattern but deviates in small but significant ways. These inconsistencies make it hard to use with existing CBV libraries and disrupt the familiar Django workflow.

Key Issues:

Object Attribute in Detail View:

In Django’s DetailView, the object is accessed with self.object, but hx_requests uses hx_object, which feels unnecessary and confusing.

Method Signatures:

Django CBVs convert kwargs into view attributes automatically, making them easy to access. hx_requests passes **kwargs directly into methods, which doesn’t align with how Django does things.

Form Handling:

Django passes the form instance to form_valid and form_invalid, which makes handling forms straightforward. hx_requests instead sets self.form instead of passing the form to the appropriate form handlers.

Model and Fields Definition for Form Views:

Django FormView allows setting model and fields in the Meta class, but hx_requests forces the creation of a custom form class, adding unnecessary steps.

Proposed Solution:

I think hx_requests classes would be much more intuitive as a view mixin. This way, we could use it with existing Django views without having to rewrite or work around the existing API. We could add custom views that inherit from Django’s generic views and include the relevant hx_request mixin to make it easier to use as an htmx view. This approach would make hx_requests easier to work with and more consistent with Django’s CBV system.

yaakovLowenstein commented 2 months ago

First of all thanks for taking the time out to write up a well thought out post.

The "Key issues" are all great points and I think it is a good idea to mimic the Django views as much as possible (already started that with latest release, but missed these points). However, it's not possible to exactly mimic and I don't think it can be a view mixin either.

Truthfully I'm not really sure what it means for them to be views instead. I think they should mimic views as much as possible for easy transition between using views and hx requests, but they can't be views. Same with a view mixin, I'm not sure what that would mean for hx requests.

sgordon16 commented 2 months ago

I understand you're view point and don't really expect it to be rewritten in this way at this point, but I do think it is a plausible approach. The idea of hx-requests from my understanding is to pass the parent view's context to the hx-requests which are essentially child views. In the view mixin we can forward the request to the appropriate child view and all you need is to pass a kwarg for the parent_view. The other "kwargs" can be passed to the child view as well. Most of the added behavior in the view is related to the response which means all you really need is a mixin that can be used in a TemplateView that overrides the render_to_response method. I'm not sure why we need to rewrite everything else. To include the parent_views context we can override get_context_data of the context mixin. Everything else is additive if I'm not mistaken.

I can make a PR to lay it out in the code but it would be quite large and I wouldn't really expect it to be merged. I guess I can always make a fork.

Regardless, the key issues listed above are my primary concerns.

Thanks for the timely response.

yaakovLowenstein commented 2 months ago

2 points

  1. I tried using a kwarg for the view so that I could use a url router instead of a mixin. However, there are too many issues with it. Because you are manually initializing the view, it does not follow the normal pattern of Django. The primary issue may be that because its not a normal request its not going through middlewares which run on the url (and you may be bypassing permissions as well). Though in your approach you still need to go through the page view which means that request is still going through the middlewares which is better than the router idea. Also manually creating the request doesn't feel natural, and if you want to use the request that went to the page view... it may have other attributes on it that do not apply to the child view (i.e resolver_match which would be from the url of the parent view but what if this other view lives in another app. I do see though that the issues I ran into when using a url router don't fully apply here
  2. The 2nd thing is that I don't think I like the idea of having views that aren't really views. They are something else so why not separate them into its own thing (like hx-requests). All these "views" are going to be in views.py files but they won't be acting as regular Django views.