Найти - Пользователи
Полная версия: CBV. Как ограничить создание по пользователю?
Начало » Django » CBV. Как ограничить создание по пользователю?
1
iceberg
Имеется три связанные между собой модели.
class MyCategory(models.Model):
    caption = models.CharField(max_length=40)
    
    class Meta:
        ordering=['id']
    def __unicode__(self):
        return self.caption
class MyItem(models.Model):
    category = models.ForeignKey(TodoCategory)
    caption = models.CharField(max_length=40)
    description = models.CharField(max_length=512)
    created = models.DateTimeField('Created time'), default=timezone.now)
    createdby = models.ForeignKey(MyUser)
    ....
    class Meta:
        ordering=['created']
        app_label = 'mysmallapp'
        permissions = (
            ('moderate_myitems', 'View, update and delete any myitems'),
        )
    def __unicode__(self):
        return self.caption
    def get_notes(self):
        return MyNote.objects.filter(itemlink=self)
class MyNote(models.Model):
    itemlink = models.ForeignKey(MyItem)
    text = models.CharField(max_length=512)
    created = models.DateTimeField('Created time'), default=timezone.now)
    ...
    
    class Meta:
        ordering=['created']
        app_label = 'mysmallapp'
        permissions = (
            ('moderate_notes', 'View, update and delete any note'),
        )

Первая модель MyCategory проблем не вызывает, ее экземпляры будут создаваться только из админки. Экземпляры двух других моделей тоже нормально создаются, редактируются и удаляются с помощью созданных на основе CBV объектов. Оргпнизация URL выглядит примерно таким образом:

urlpatterns = patterns('',
                       url(r'^item/add/$', login_required(MyItemCreateView.as_view()), 
			   name='myitem_add'),
		       url(r'^item/(?P<pk>\d+)/edit/$', login_required(MyItemEditView.as_view()), 
			   name='myitem_edit'),
		       url(r'^item/(?P<pk>\d+)/delete/$', login_required(MyItemDeleteView.as_view()), 
			   name='myitem_delete'),
		       url(r'^item/(?P<numer>\d+)/add/$', login_required(MyNoteCreateView.as_view()), 
			   name='mynote_add'),
		       url(r'^note/(?P<pk>\d+)/edit/$', login_required(MyNoteEditView.as_view()), 
			   name='mynote_edit'),
		       url(r'^note/(?P<pk>\d+)/delete/$', login_required(MyNoteDeleteView.as_view()), 
			   name='mynote_delete'),
                       )
Теперь встала задача, чтобы каждый пользователь не мог редактировать, удалять и создавать то, что принадлежит другому пользователю.

Для MyItemEditView, MyItemDeleteView, MyNoteEditView и MyNoteDeleteView это делается легко путём переопределения get_queryset.

def get_mynotes_queryset(self):
    if self.request.user.has_perm('mysmallapp.moderate_notes'):
        return MyNote.objects.all()
    else:
        return MyNote.objects.filter(itemlink__createdby=self.request.user)
class MyNoteEditView(UpdateView):
    model = MyNote
    form_class = MyNoteForm
    ...
    get_queryset = get_mynotes_queryset
class MyNoteDeleteView(DeleteView):
    model = MyNote
    template_name = ...
    ...
    
    get_queryset = get_mynotes_queryset

Вопрос: как сделать то же самое для MyItemCreateView и ограничить доступ другим пользователям для создания MyNote, ссылающимся на чужие экземпляры MyItem ?

То есть если некий пользователь идет по ссылке /item/3/add/, а экземпляр MyItem с pk, равным 3, принадлежит другому пользователю, то пользователь отфутболивался ещё до отправки заполненной им формы на создание нового экземпляра MyNote.

Пока что у класса MyNoteCreateView переопределен следующий метод:
    def form_valid(self, form):
        nlink = get_object_or_404(MyItem, pk=self.kwargs['numer'])
        form.instance.itemlink = nlink
        return super(MyNoteCreateView, self).form_valid(form)
FishHook
Переопределяйте dispatch, если юзер пытается сделать бяку райзим PermissionDenied, до гета и поста дело вообще не дойдет, а до form_valid и прочих специфических методов тем более. Разумно организовать это в виде миксина.
iceberg
С dispatch кажется понял, спасибо, а вот про миксины можно ткнуть пальцем хотя бы направление? О миксинах в документации почитал, но поскольку до сих пор не могу полностью привыкнуть к CBV, с решением пока не сориентируюсь.
FishHook
Ок, в чем преимущество CBV перед классическими вьюхами-функциями?
В наследовании, во множественном наследовании. Миксин - это такой класс, который сам по себе не может быть представлением, но участвуя в наследовании он наделяет другие классы полезными свойствами.

class PermissionResolverMixin(object):
    def dispatc(self, request, *args, **kw):
        if ....
              self.item = ...
        else:
              raise PermissionDenied()
        return super(PermissionResolverMixin, self).dispatc(self, request, *args, **kw)
class MyView(PermissionResolverMixin, UpdateView):
     pass

Ваша вьюшка теперь имеет self.item или вернет 403.
FishHook
iceberg
Когдап говорят спасибо, ставят не минус, а плюс.
iceberg
FishHook
icebergКогдап говорят спасибо, ставят не минус, а плюс.
Вау, не знаю, как так получилось, конечно же имел в виду плюс. Сам в шоке. А как теперь это можно исправить? С радостью удалил бы свой минус из кармы, но нет такой возможности. Просьба администрации поменять в посте мой минус на плюс.
iceberg
Сделал через переопределение dispatch без миксинов. С миксинами тоже разобрался, меня смутило использование в методах миксинов атрибутов, которых у них может не быть, не дошло, что наследование производится не от одного миксина, а от двух классов.

FishHook, спасибо за наводку.

Ок, в чем преимущество CBV перед классическими вьюхами-функциями?
Концептуально может быть преимущества и нет, но под CBV уже создано много полезных классов и глупо ими не пользоваться. Если говорить об отдельно взятой вьюхе, раз уж остальное написано в CBV, пусть и эта будет тоже. Как выяснилось, это не так сложно.
FishHook
iceberg
Концептуально может быть преимущества и нет
Конечно, есть. Ровно те же преимущества, которые есть у ООП относительно процедурного программирования.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB