mardi 24 novembre 2015

Design mixin classes

Initial situation

I have one app, 'devices' with some views:

class DeviceUpdateView(LoginRequiredMixin, UpdateView):
    model = Device
    form_class = DeviceEditForm

    def get_form(self, form_class=None):
        form = super(DeviceUpdateView, self).get_form(form_class=None)
        form.fields['beacon'].queryset=Beacon.objects.filter(customer_account=self.request.user.default_customer_account)
        return form

class DeviceCreateView(LoginRequiredMixin, CreateView):
    model = Device
    form_class = DeviceEditForm

    def get_initial(self):
        initial = super(DeviceCreateView, self).get_initial()
        initial['customer_account'] = self.request.user.default_customer_account
        return initial

    def get_form(self, form_class=None):
        form = super(DeviceCreateView, self).get_form(form_class=None)
        form.fields['beacon'].queryset=Beacon.objects.filter(customer_account=self.request.user.default_customer_account)
        return form

I have another app ('buildings') vith this view:

class BuildingCreateView(LoginRequiredMixin, UserFormKwargsMixin, CreateView):
    model = Building
    form_class = BuildingEditModelForm

    def get_initial(self):
        initial = super(BuildingCreateView, self).get_initial()
        initial["customer_account"] = self.request.user.default_customer_account
        return initial

DRY Mixin

Now, I want to factorize my code in order to be more "DRY".

I then create this mixin, in my devices/views.py:

class BeaconFilterMixin(object):
    def get_form(self, form_class=None):
        form = super(BeaconFilterMixin, self).get_form(form_class=None)
        form.fields['beacon'].queryset=Beacon.objects.filter(customer_account=self.request.user.default_customer_account)
        return form

And my views become:

class DeviceUpdateView(LoginRequiredMixin, BeaconFilterMixin, UpdateView):
    model = Device
    form_class = DeviceEditForm


class DeviceCreateView(LoginRequiredMixin, BeaconFilterMixin, CreateView):
    model = Device
    form_class = DeviceEditForm

    def get_initial(self):
        initial = super(DeviceCreateView, self).get_initial()
        initial['customer_account'] = self.request.user.default_customer_account
        return initial

Nice and sweet!

Now the question

I want to do exact same thing and create a "InitialCustomerAccountMixin" that could be used by both 'buildings' and 'devices' apps.

The code will be:

class InitialCustomerAccountMixin(object):
    def get_initial(self):
        initial = super(InitialCustomerAccountMixin, self).get_initial()
        initial['customer_account'] = self.request.user.default_customer_account
        return initial

The question is: where do I put my mixins code? For an 'app-scope' mixin, I get that I should put the code in the views.py or in a mixins.py file in the app. But for a 'multi-app' mixin, I don't know the design principle to follow.

Aucun commentaire:

Enregistrer un commentaire