GithubHelp home page GithubHelp logo

Comments (21)

gregmuellegger avatar gregmuellegger commented on July 27, 2024

As discussed:

  • If you need to store state during a request, you can do that on the view, since it's save to do in CBVs.
  • We need to document that it's not possible to save state on the modeladmin that is not allowed to endure more than request-response cycle.
  • We should add in-code comments to explain the same.

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

@freakboy3742 and I realized we can pass to the views a default list of values/methods/properties and take out the ModelAdmin2 object.

If the user wants to add more fields, they can add them by writing them to a list, perhaps called ModelAdmin2.dataset.

from django-admin2.

RaphaelKimmig avatar RaphaelKimmig commented on July 27, 2024

Most objects that one could potentially use to store state on have a lifetime greater than the request/response cycle.
Admin2 (as opposed to django.contrib.admin) does have an obvious place to store state (the views) that is also safe.
Thus I think documenting the issue and showing how to do it the right way (just use the view) should be enough.

from django-admin2.

AndrewIngram avatar AndrewIngram commented on July 27, 2024

It was my understanding that we added in passing the modeladmin to the view as a quick way of getting permissions up and running. Given that all of the views will be returning TemplateResponse objects we can add the permissions to the context as a wrapper function rather than in the view code itself.

from django-admin2.

AndrewIngram avatar AndrewIngram commented on July 27, 2024

I've got a branch with that deals with the template context part of the modeladmin dependency (https://github.com/AndrewIngram/django-admin2/compare/remove-modeladmin-from-view-instance). Need to think about how view-level permissions should be treated. Can someone expand on the permission object concept in issue #96? It might be the solution to this half of the problem.

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

I talked it out with @freakboy3742 and he suggested something similar to what is in @AndrewIngram's branch. I'll review it in the morning. 😪

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

@RaphaelKimmig - We'll definitely have to warn developers in the docs because even with better state handling in views we still risk them mucking around with the ModelAdmin object. Once we get the code down let's do that perfectly. Kick-butt docs are a must!

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

@AndrewIngram - Can you take a look at rbaf573b. It's rough and it seems to do exactly what I want:

  1. Copy a limited set of ModelAdmin attributes to an ImmutableAdmin object.
  2. We provide a default set, but the developer can override it by setting ModelAdmin2.model_admin_attributes. We do this to avoid the potential performance penalty for groups with gigantic data sets.

from django-admin2.

AndrewIngram avatar AndrewIngram commented on July 27, 2024

What will happen if a mutable object is copied to ImmutableAdmin? It seems that whilst we wouldn't be able to modify the ImmutableAdmin itself, we'd still be able to change the attribute objects, which would be references back to those on the original ModelAdmin.

from django-admin2.

inglesp avatar inglesp commented on July 27, 2024

I've added a comment to baf573b, but I'm not sure if that will end up getting linked to this issue.

from django-admin2.

AndrewIngram avatar AndrewIngram commented on July 27, 2024

I'm still leaning towards only passing necessary fields to the views and no longer pass the modeladmin2. It's always possible to override get_default_view_kwargs on any modeladmin2, and it seems that at the moment we're mostly trying to engineer a solution to avoid passing a dictionary with 4 extra items in it.

from django-admin2.

inglesp avatar inglesp commented on July 27, 2024

This feels right to me too. Can we enumerate a list of the fields that we expect to pass to the views?

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

The problem with passing in lots of arguments is as follows: Since Django views only accept init arguments that are already defined as attributes, any new arguments added will force the users to admin2 to modify potentially all their view classes. This will prove to be a very unpopular with users of admin2, not to mention ourselves.

The answer is passing in a collection of attributes, either as a dictionary or a class. For this sort of thing I prefer to use classes/objects because it's consistent with the rest of the project's use of classes.

from django-admin2.

AndrewIngram avatar AndrewIngram commented on July 27, 2024

Another option is to re-evaluate whether the modeladmin object itself should be responsible for managing the permissions of all its subviews, or whether the views themselves should handle it. If these same views were being used outside the context of an admin rebuild we wouldn't think twice about using a permission mixin or decorator and being done with it, what's the special case that makes the admin different?

from django-admin2.

gregmuellegger avatar gregmuellegger commented on July 27, 2024

I have some ideas of making the permission handling a bit easier by having a new Permissions object that will have the necessary logic attached. So we only end up passing one variable into the template. I'm going to show some code of how I think this could work later today.

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

@AndrewIngram It's not just the permissions, it's other things to pass from the ModelAdmin object. Things like list_filters, sort_filters, fields, and much more. For example, even without the audit I think we all suspect will happen, the list of fields at https://github.com/twoscoops/django-admin2/blob/master/djadmin2/models.py#L24-L54 is too long to pass into every view declaration.

Having developers (and us) have to define 15+ arguments to make a valid Admin2 view seems a bit off. On the other hand, that's what base view classes are for, right? Hmmm... maybe that's it.

from django-admin2.

gregmuellegger avatar gregmuellegger commented on July 27, 2024

After hacking a bit on the permissions (see #96 (comment)) I more and more think that it is not really practical to keep the model_admin out of the view.

I think if we do this, we dig ourselves a hole that will not kill us but will always be an annoyance. I still see @pydanny's concerns regarding that users might shoot their self in the foot, however I don't think it's worth the trade-off.

I for myself wouldn't even think of saving state to the model_admin because when coding in the view itself, it is so obvious that self is the thing that holds the state, since it already owns attributes like self.request, self.object, self.queryset, etc...

And the view has access to so many more things that the user can use to run amok with if he really wants to. Like the self.model which will be available from the view as well.

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

The problem with providing a modifiable model_admin in the view is that while @gregmuellegger (or @AndrewIngram, @inglesp, @audreyr, etc) wouldn't do it, developers with less experience (@pydanny 😉) might. In fact, the documentation for modifying state in django.contrib.admin.ModelAdmin is not easily discoverable.

Hence why a simple wrapper object, perhaps better than the simple one I found, would be ideal.

from django-admin2.

gregmuellegger avatar gregmuellegger commented on July 27, 2024

The view already holds a few objects that are not immutable and by this are also in danger to get state attached by the user. But django doesn't do anything about it either.

Some examples:

  • View.model
  • View.paginator_class
  • View.response_class
  • View.queryset

I know that these examples are mostly classes and not instantiated objects. But I think my argument is still valid 😉 The point I'm trying to make is that why should we protect the user from doing:

class MyView(Admin2View, ...):
    def get(self):
        # saving state here to the model_admin instance
        self.model_admin.request = self.request

... if the user is still able to do the following:

class MyView(Admin2View, ...):
    def get(self):
        # saving state here to the model class
        self.model.request = self.request

Please don't be offended, I really try to argue with all admin2 users in mind, not just me. If @pydanny keeps with his reasons against passing the model_admin directly, I will stop bike shedding ofcourse 😉

from django-admin2.

RaphaelKimmig avatar RaphaelKimmig commented on July 27, 2024

I agree. To me this feels like a solution looking for a problem. Most objects
(more or less everything but the view and it's parameters) have a life-cycle
that is longer than the request-response cycle and thus should not be used to
store state for views.

I do agree that with django.contrib.admin there is a problem with state.
The old admin is a class based view yet you mustn't store state on self
because it lives longer than a single request/response cycle.
There, a view is a, and uses, dozens of methods on the ModelAdmin instance to
create a response and there are several places where methods can not be
simply overriden to provide a certain functionality because they do not have
access to some of the view's state.
As a python developer it seems natural to put state that is shared between
methods into instance variables. Now we have the unfortunate situation of there
being an obvious way to do something yet that being the wrong way.

In admin2 we do not suffer the same problem because we use Django's class based
views for most functionality. When a developer wants to customize a view
beyond settings basic variables the default approach will be to subclass the
respective admin view. Here they can use the view instance to store state. This
is the intuitive way of doing it and this is the way it is going to be
documented. So in the admin2 scenario we have an obvious way of doing things
that is also the correct way.

from django-admin2.

pydanny avatar pydanny commented on July 27, 2024

We know that saving to the model_admin object is dangerous because @freakboy3742 and the divio team both reported it as an issue. On the other hand, @gregmuellegger pointed out that developers can save to the model class and it's potentially dangerous. @RaphaelKimmig states that we should encourage developers to save state to the view since that's what should be happening, that it's obvious, and it's the correct way.

However, one thing we need to consider is that we are creating an extensible, adaptable version of the admin. Developers are going to get creative and 'experts' are going to advocate monkeypatching things without thinking about problems down the road (take a look at some of the advice for hacking the User model to see what I mean). While we are all consenting adults, there is something to be said about not letter developers dig deep holes for themselves and their projects.

For example, did you know I'm known for adding attributes and methods on model classes on the fly? Works fine in normal architectures, but in django-admin2 it might be a problem.

Dictator's Determination

I'm pulling out the dictator card here. :neckbeard:

However, please read on and don't be upset even though I'm mandating we're going forward with locking down the model_admin class.

Yes, we are going to do is constrain the model_admin class and make what is passed into the views immutable using something better than my simple hack. If possible, we'll also do this to the model classes, but that might have weird repercussions that we won't understand until we finish documenting django.db.models.Model._meta.

Please consider that if we lock things down now, and it turns out that it's a good thing, then we all win. If it turns out to be a hindrance, our documentation explicitly says what not to do, and performance analysis says the lockdown slows down the app, then we can 'liberate' the model_admin. Again, we win. 😄

Here's the scenario I considered when making this decision: We open things up right now and realize later it was a huge mistake. Now we have to lock things down and we SHATTER backwards compatibility with whatever hacks and monkeypatches were created against django-admin2. Rants about it go viral and people misunderstand whatever we are fixing. It's a nightmare scenario, but these sorts of viral explosions are know to happen.

So again, the lockdown continues and we'll be exploring better Immutable/Frozen class objects.

from django-admin2.

Related Issues (20)

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.