-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Class-based views #22
base: master
Are you sure you want to change the base?
Conversation
blog/views.py
Outdated
@@ -3,115 +3,136 @@ | |||
- post_list - returns post list; | |||
""" | |||
|
|||
from django.shortcuts import render, get_object_or_404, redirect | |||
from django.shortcuts import get_object_or_404, redirect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't need these shortcuts as well.
blog/views.py
Outdated
template_name = 'blog/post_edit.html' | ||
|
||
def post(self, request, *args, **kwargs): | ||
"""Get author-field from request and save post to DB.""" | ||
form = PostForm(request.POST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe, this check is already encapsulated into CreateView.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this
blog/views.py
Outdated
template_name = 'blog/post_edit.html' | ||
|
||
def post(self, request, *args, **kwargs): | ||
"""Get author-field from request and save post to DB.""" | ||
form = PostForm(request.POST) | ||
if form.is_valid(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe, this check is already encapsulated into CreateView.
blog/views.py
Outdated
template_name = 'blog/post_edit.html' | ||
|
||
def post(self, request, *args, **kwargs): | ||
"""Get author-field from request and save post to DB.""" | ||
form = PostForm(request.POST) | ||
if form.is_valid(): | ||
post = form.save(commit=False) | ||
post.author = request.user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can inner this via form_valid method or so
blog/views.py
Outdated
template_name = 'blog/post_edit.html' | ||
|
||
def post(self, request, *args, **kwargs): | ||
"""Get author-field from request and save post to DB.""" | ||
form = PostForm(request.POST) | ||
if form.is_valid(): | ||
post = form.save(commit=False) | ||
post.author = request.user | ||
post.save() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done automatically, you don't have to implement post method at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quess, I have to use construction on 55-57 anyway - not in post, but in form_valid then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there should probably be a way to even encapsulate that into save method of form
blog/views.py
Outdated
fields = ['title', 'text'] | ||
template_name = 'blog/post_edit.html' | ||
|
||
def get_success_url(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better move this to model
blog/views.py
Outdated
class PublishPost(TemplateView, Protected): | ||
"""View for publishing post.""" | ||
|
||
def get(self, request, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be post
blog/views.py
Outdated
queryset = Post.objects.filter(published_date__isnull=True).order_by('created_date') | ||
|
||
|
||
class PublishPost(TemplateView, Protected): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use updateview
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or so
blog/views.py
Outdated
fields = ['author', 'text'] | ||
template_name = 'blog/add_comment.html' | ||
|
||
def post(self, request, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: read the docs of what each of base classes implement/encapsulate
blog/views.py
Outdated
comment = get_object_or_404(Comment, pk=kwargs['pk']) | ||
post_pk = comment.post.pk | ||
comment.delete() | ||
return redirect('post_detail', pk=post_pk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about get_success_url?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried, but didn't figure out, how to get post.pk.
get_success_url evaluates after the action is done, so I can't get it from self.object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd save it in form_valid and then reused that to create success url
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I was wrong - we can get self.object.
https://code.djangoproject.com/ticket/19044
But right now it fails on template rendering (cuz post object is missing). I can write separate template for deleting or redefine get method (weird solution, I guess)...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. Let's leave it as it. It would be cleaner in case of doing normal CRUD for some JS client.
blog/models.py
Outdated
|
||
def get_absolute_url(self): | ||
"""Redirect to view with detail info about parent post.""" | ||
return reverse('post_detail', args=[str(self.post.pk)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, pk=self.post.pk
should work just fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't, reverse() accepts only args / kwargs for additional parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh then you should pass kwargs, singe you use named group pk
in that regexp
blog/models.py
Outdated
@@ -59,3 +59,7 @@ def approve(self): | |||
def __str__(self): | |||
"""Represent a comment as a string by its text.""" | |||
return self.text | |||
|
|||
def get_absolute_url(self): | |||
"""Redirect to view with detail info about parent post.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a like. No redirect here at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's rendering/returning url, nothing more
blog/views.py
Outdated
def form_valid(self, form): | ||
"""Pass parent post pk to model.""" | ||
post = self.get_object(Post.objects.filter(pk=self.kwargs['pk'])) | ||
form.save(post) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pointless: you get object from the db and save it back? That's weird
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get Post object and save it as a field of Comment.
Though, working with keys instead of objects should be simplier.
blog/views.py
Outdated
"""Pass parent post pk to model.""" | ||
post = self.get_object(Post.objects.filter(pk=self.kwargs['pk'])) | ||
form.save(post) | ||
return super(AddComment, self).form_valid(form) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Python 3, super is simpler
@@ -1,8 +1,10 @@ | |||
*.pyc | |||
__pycache__ | |||
tvenv | |||
djenv |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just use pyenv's virtualenv plugin and forget about in-project env dir?
blog/forms.py
Outdated
@@ -13,6 +13,14 @@ class Meta: | |||
model = Post | |||
fields = ('title', 'text',) | |||
|
|||
def save(self, user=None): | |||
"""Save post to DB, assigning author field.""" | |||
post = super(PostForm, self).save(commit=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not py2
blog/urls.py
Outdated
url(r'^post/(?P<pk>\d+)/comment/$', views.AddComment.as_view(), name='add_comment'), | ||
url(r'^comment/(?P<pk>\d+)/approve/$', views.ApproveComment.as_view(), name='comment_approve'), | ||
url(r'^comment/(?P<pk>\d+)/remove/$', views.RemoveComment.as_view(), name='comment_remove'), | ||
url(r'^admin/', admin.site.urls), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't it already added in mysite
?
blog/views.py
Outdated
"""Publish post.""" | ||
post = self.get_object(Post.objects.filter(pk=kwargs['pk'])) | ||
post.publish() | ||
return HttpResponseRedirect(reverse('post_detail', kwargs={'pk': post.pk})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use UpdateView
, there's a plenty of logic encapsulated there. You should just inject a small change into some of already existing methods. It will get redirected automatically. BTW, there should be self.object
available, which is handled so you don't have to do manual db lookup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.object assigns in BaseUpdateView.get(), so I should write smthg like:
super.get(...)
DoSmthg (self.object.publish etc.)
return HttpResponseRedirect(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're missing the idea of pre-existing base classes. post/get/put etc. methods are low-level here. But those classes like UpdateView and similar encapsulate lots of logic and provide you with custom hook methods, which you should modify to inject some changes into existing flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, I miss the idea, where should I implement logic in general - or just couldn't find an appropriate method to make an injection.
self.object instead of get_object.
def save(self, user=None): | ||
"""Save post to DB, assigning author field.""" | ||
post = super().save(commit=False) | ||
if user: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why exactly do you forbid setting NULL for the author?
@@ -27,6 +28,10 @@ def publish(self): | |||
self.published_date = timezone.now() | |||
self.save() | |||
|
|||
def get_absolute_url(self): | |||
"""Return url for view with detail info about post.""" | |||
return reverse('post_detail', args=[self.pk]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd do kwargs instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
|
||
def form_valid(self, form): | ||
"""Pass request.user to model.""" | ||
form.save(self.request.user) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, form.save()
is already being called after form_valid()
by the base view's logic. I think, you probably should only modify the instance like form.instance.author = self.request.user
and that's it:
https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-editing/#models-and-request-user
fields = ['title', 'text'] | ||
template_name = 'blog/post_detail.html' | ||
|
||
def get(self, request, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's weird: why not just POST
the change and let update view to handle all internal logic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I remove publish() method from model then? And just pass published_date change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, that method is handy
|
||
def form_valid(self, form): | ||
"""Pass parent post pk to model.""" | ||
post = self.get_object(Post.objects.filter(pk=self.kwargs['pk'])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(same as above)
model = Comment | ||
fields = ['author', 'text'] | ||
|
||
def get(self, request, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decide whether you use UpdateView or go for smth simpler.
According to #20 , changed functional-based views to cb approach.