LBD_23
LBD_23

Reputation: 35

How can I avoid repetition of code within a function-based view in Django?

I have been researching how can I avoid using snippet of code over and over. The answer probably will involve using (generic) Class-based functions. However, I am a beginner in Django and this seems confusing. Here is my view in views.py:

@login_required(login_url='/login')
def view_list(request, listing_id):
bid = Bid.objects.all().filter(listing=listing_id).order_by('-id')
b_u = bid[0].user
listing = Listing.objects.get(pk=listing_id)

if request.method == "GET":
    return render(request, "auctions/view_list.html", {
        "form": BidForm(),
        "total_bids": bid.count(),
        "bid":  None if bid == 0 else bid[0].bid,
        "listing": listing,
        "bid_user": "Your bid is the current bid." if request.user == b_u else None
    })
else:
    form = BidForm(request.POST)
    if form.is_valid():
        value = form.cleaned_data
        if value['bid'] <= bid[0].bid:
            error_check = True
            return render(request, "auctions/view_list.html", {
                "error_check": error_check,
                "alert": f"Your bid is lower than the current bid $({bid[0].bid})! Try placing a higher one.",
                "form": BidForm(),
                "total_bids": bid.count(),
                "bid":  None if bid == 0 else bid[0].bid,
                "listing": listing,
                "bid_user": "Your bid is the current bid." if request.user == b_u else None
            })
        else:
            error_check = False
            new_bid = form.save(commit=False)
            new_bid.user_id = request.user.id
            new_bid.listing_id = listing.id
            new_bid.save()
            return render(request, "auctions/view_list.html", {
                "error_check": error_check,
                "alert": "Your bid was successfully placed!",
                "form": BidForm(),
                "total_bids": bid.count(),
                "bid":  None if bid == 0 else bid[0].bid,
                "listing": listing,
                "bid_user": "Your bid is the current bid." if request.user == b_u else None
            })

And here is my template code:

{% extends "auctions/layout.html" %} 
{% load humanize %}
{% load crispy_forms_tags %}

{% block body %}
    {% if error_check == True %}
        <div class="alert alert-warning" role="alert">
            {{ alert }}
        </div>
    {% elif error_check == False %}
        <div class="alert alert-success" role="alert">
            {{ alert }}
        </div>
    {% endif %}
    <div>
        <h3>Listing: {{ listing.title }}</h3>
        <img src="{{ listing.image }}" alt="Listings' Images">
        <p>{{ listing.description }}</p>
        {% if not bid %}
            <strong>${{ listing.price|stringformat:"1.2f" }}</strong>
        {% else %}
            <strong>${{ bid|stringformat:"1.2f" }}</strong>
        {% endif %}
        
        <p> {{ total_bids }} bid(s) so far. {% if bid_user %} {{ bid_user }} {% endif %}</p>
        <form method="POST" name="bidding" action="{% url 'view_list' listing.id %}">
            {% csrf_token %}
            <div class="input-group mb-3">
                <div class="input-group-prepend">
                    <span class="input-group-text">$</span>
                </div>   
                <div style="margin: 0; padding: 0 2px; height: 6px;">
                    {% crispy form %}
                </div>   
                <div class="input-group-append" >
                    <span class="input-group-text">.00</span>
                </div>
                <input type="submit" class="btn btn-primary" value="Place Bid">
            </div>
        </form>
        <h4>Details</h4>
            <li>Listed by: {{ listing.user }} </li>
            <li>Category: {{ listing.category }} </li>
            <li>Listing created at: {{ listing.created_at }} </li>
    </div>

{% endblock %}

So how can I avoid all this repetition and make the code more succinct. Also, this way when the user places a successful bid, the rendered template does not contain the new information from the form.

Upvotes: 0

Views: 97

Answers (1)

mrvol
mrvol

Reputation: 2963

The pattern is very simple

def some_view(request):
    form = SomeForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        # Form processing
    return render(request, "auctions/view_list.html", {
                "form": form
    })

Upvotes: 2

Related Questions