Coder Social home page Coder Social logo

Restrict Creation of new Tags about django-tagulous HOT 9 OPEN

toabi avatar toabi commented on August 16, 2024
Restrict Creation of new Tags

from django-tagulous.

Comments (9)

radiac avatar radiac commented on August 16, 2024 1

Thanks very much for your PR! It's always great to have contributions, and I really appreciate your effort.

Before I merge though, it would be good to get an idea of your use case. If a dev sets the flag in the tag options, do I understand the intent is to turn it into a multiple choice field for all users of the form?

I'm a bit worried about relying on js to enforce a rule like this - as a user my expectation would be that this flag would be trusted, set and forget; leaving the server-side enforcement as an exercise for the reader may be tricky, as from memory I don't think we offer much to help spot from a form or view which values are changing. It would also be easy for a dev to forget and not notice because they're using js. It feels like we're creating a potentially dangerous foot gun.

If I've understood the goal correctly, it may be safer to just use a MultipleChoiceField with a select2 widget.

Thinking out loud though, I wonder if some or most use cases for restricting a tag field would depend on who is seeing the field, not just which form it is in. That would need to be controlled from somewhere that has access to the request object - so most likely the form constructor. That would mean we'd need a way to manage different tagfield options on individual bound tag field, which I don't think we have at the moment.

This then ties into something mentioned earlier in the thread about permissions, which again may need to be handled with the request. I hadn't run into that specific use case myself, but over the past year or so I've noticed a similar missing feature - I want to be able to filter non-initial tags by a value or another field on the tagged model (a related object, limit tag visibility to those who created it, only list children of the currently-selected tag tree tag etc). Some relational queryset filtering could be done in the tag options without a request, but I suspect that wouldn't go far enough.

It feels like both of these issues could have a similar solution - possibly options in the form constructor, one to pass a filtered tag queryset, one to disable adding tags. It would be nicer to put the filter as a callable in the tag options, but I don't think the request can make it that far. I've been trying to resist it, but I think we need to introduce a tagfield-aware base form class, which is a whole new can of worms.

I'll give this all some more thought and see how it can fit together when I get back into the project code in the next few weeks - in particular how to manage the form and field classes, and whether we want to be able to customise some or all tag options on each request.

Thanks again!

from django-tagulous.

radiac avatar radiac commented on August 16, 2024

There's no way to stop people from adding tags at the moment, although it's an interesting idea, and one someone else asked for too.

What's your use case? If you just want the same visual effect but with hard-coded options, you'd probably be better off just using a charfield with a standard choices tuple, then use select2 directly to manage the drop-down - but I could certainly see a use for supporting permission-based tag creation, ie so only admins or certain users can add tags. I'll bear it in mind for a future version.

from django-tagulous.

toabi avatar toabi commented on August 16, 2024

Yes, permission-based tag creation would be even better.

I'm looking for a nice way to categorise content, similar to https://github.com/callowayproject/django-categories – which isn't python3 compatible. Hardcoded select values are not an option because there are imports which have to create tags on the fly. But users should generally not allowed to create them.

Because this functionality will be used quite a bit, it's would be not very "DRY" to handcraft all the needed Models by hand. And other tagging solutions often don't properly support different "dictionaries" of tags.

from django-tagulous.

torstenfeld avatar torstenfeld commented on August 16, 2024

I was just about to ask for the same / a similar feature. My use case is that I have a TagTreeModel with product/module combinations. For visualization and reporting topics, I like the TagTree feature to search for descendents, children, etc.
As the list of combinations is pretty static I wanted to restrict the creation of new tags as well.

from django-tagulous.

toabi avatar toabi commented on August 16, 2024

@radiac I'm looking at tagging libraries again, is this feature now possible? :)

from django-tagulous.

SLiNv avatar SLiNv commented on August 16, 2024

Can we just in the frontend don't allow user to input but only search and select existing tags?

from django-tagulous.

calummackervoy avatar calummackervoy commented on August 16, 2024

I believe that this could be implemented by setting tags on the select2 to false (following some instruction on the user's form field), and then server-side by implementing validation on the form field which ensures the tag submitted exists?

I tested and for select2-3 createSearchChoice can return null

from django-tagulous.

calummackervoy avatar calummackervoy commented on August 16, 2024

I've opened a PR for the front-end aspect of this #180

Personally I think it should be OK to leave the validation of request data to the API developer - e.g. they might be using a serializer or the admin site instead of a form anyway:

Once merged then you can set a new tag option allow_create to tweak this behaviour in the form

In the meantime I've also found a workaround using jQuery (works only with version 3 but this issue might help getting it to work with v4):

$( document ).ready(() => {
    if($("#s2id_id_myfield").length) {
        $("#s2id_id_myfield").data("select2").opts.createSearchChoice = () => {return null}
    }
});

document.ready makes sure that it runs after tagulous has initialised the select2 component

from django-tagulous.

calummackervoy avatar calummackervoy commented on August 16, 2024

Hi! My use case is that I have a SingleTagField which should let users select from a dropdown of tags, but not to add their own. In the PR, if a dev sets the allow_create option to False, then the select2 component will have the correct properties set to prevent the creation of new tags (in both versions 3 and 4). When I tested locally I found that if I typed "existing tag" I was able to select the tag, but if I typed "non existing tag" then I had no options to select, where currently I would be given the option to select it anyway and create a new tag

I'm a bit worried about relying on js to enforce a rule like this

In my use case I wrote the view which accepts the form to strip the tag from the request if it doesn't already exist - I did this because it's a quick solution and the form validation code looked complex. I figured that the tag field could be getting created from a form, from the admin, from a serializer (DRF), mutation (GraphQL), the shell or otherwise in code - so backend protection would be happening in potentially many places depending on where the setting was applied. It was a convenient excuse not to provide it

It feels like we're creating a potentially dangerous foot gun.

I agree it would be better if the developer didn't have anything to do

If I've understood the goal correctly, it may be safer to just use a MultipleChoiceField with a select2 widget.

Looking at the Django docs for MultipleChoiceField very briefly, it looks like I'd need to get creative to allow for 1000+ tag options and the fact that the tags do still change in real-time (just not from this form I'm exposing to the user). With that in mind I prefer the workaround I posted before (adding JS to change the select2 component after the tagulous JS has run)

would depend on who is seeing the field, not just which form it is in

Good point. There may be a solution somewhere which allows for using a callable for the option allow_create (taking parameter request) and then in the form constructor binding the request to it

from django-tagulous.

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.