TimJ
TimJ

Reputation: 399

Possible to make these two django views DRY-er?

I'm currently learning the Python / Django stack by following some training to build a blog.

I currently have two similar views for adding new and editing existing posts (post_new and post_edit) as below:

def post_new(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            return redirect("post_detail", pk=post.pk)      
    else:
        form = PostForm()    
    return render(request, "blog/post_edit.html", {"form": form})


def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user 
            post.published_date = timezone.now()
            post.save()
            return redirect("post_detail", pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, "blog/post_edit.html", {"form":form})

Although these views do different jobs they share some identical code.

Trying to follow best practice (DRY), is there a sensible way to make such similar views DRYer? Or is it better to leave views of this sort of length in long form to keep them easy to read?

Upvotes: 1

Views: 74

Answers (2)

ilse2005
ilse2005

Reputation: 11439

You probably want to use Class-based views for that.

from django.views.generic.edit import CreateView, UpdateView

class PostCreate(CreateView):
    model = Post
    fields = ['name', ...]

class PostUpdate(UpdateView):
    model = Post
    fields = ['name', ...]

Upvotes: 0

Gert
Gert

Reputation: 532

I would personally write it like this:

def post_edit(request, pk=None):
    if pk is not None:
        post = get_object_or_404(Post, pk=pk)
    else:
        post = None
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user 
            post.published_date = timezone.now()
            post.save()
            return redirect("post_detail", pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, "blog/post_edit.html", {"form":form})

Basically, you pass the default instance value to the ModelForm.

Upvotes: 4

Related Questions