encode / django-vanilla-views

Beautifully simple class-based views.
http://django-vanilla-views.org/
BSD 2-Clause "Simplified" License
985 stars 74 forks source link

Passwords in vanilla create/update views #52

Closed bcoover closed 8 years ago

bcoover commented 8 years ago

Hi, I ran into a problem in my app with vanilla views as it relates to passwords. As you know, passwords have to be hashed before saving. When using the vanilla-generated create and update views, the password was not getting saved correctly via hashing, and looking at those objects i the admin, I got the error "Invalid password format or unknown hashing algorithm" I understand that vanilla, by design, treats all fields the same, which is fine, but in special cases this may break down. For common use cases like passwords, it would be nice to have them handled automatically. I didn't find anything when Googling this in reference to django-vanilla-views, so (IMHO) I think this would be a good addition to the documentation...

FYI, in my app I am doing a couple of slightly non-standard things:

My workaround was adding this override function 'form_valid' to the create and update views to ensure that this field was treated correctly:

from vanilla import CreateView, DeleteView, ListView, UpdateView, DetailView
from django.contrib.auth.hashers import make_password

class CustomCreateView(CreateView):
        def __init__(self, model, form_class):
        self.model = model
        self.form_class = form_class

    def form_valid(self, form):
        self.object = form.save(commit=False)
        form_data = form.cleaned_data
        try:
            if form_data['password']:  # case for user accounts
                self.object.password = make_password(form_data['password'])
        except KeyError:
            pass
        self.object.save()
        return HttpResponseRedirect(self.success_url)

    class Meta:
        view_abstract = True  # really just documentation

class CompanyCreate(CustomCreateView):
    this_model = Company
    this_form_class = CompanyForm

    def __init__(self, model=this_model, form_class=this_form_class):
        super().__init__(model, form_class)
tomchristie commented 8 years ago

If you can demonstrate that vanilla views are different to Django's implementation in this regard then we could consider this. Otherwise, not. We mirror their behavior but with a cleaner implementation and interface. Nothing more than that.