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)