Search code examples
pythondjangodjango-forms

Instantiating a form in a view for a get request, why asks for 'request' argument?


When instantiating a form inside the view function e.g form = submit_bid() django crashes and gives the error " submit_bid() missing 1 required positional argument: 'request' ".

I'm recreating a auction site (eBay like). One of the views (view_listing) returns a template where among other things it have an input field so the user can set his own bid on the listing. The thing is that when i create the form = submit_bid() in the view to serve it to the template, i obtain the error that needs a 1 positional argument request (for what i understand i only need pass this on a POST request, and im actually working on the GET request to serve the form to the template). So django crashes. I also have another view (create_auction) where i instantiated a form succesfully (like i described before form = create_auction() and works flawesly, but in this particular view im getting problems. I will leave the code from my forms.py, also of the view. I have to mention that im new to django, and this are my first attemps to working with it

forms.py:

from django import forms
from .models import Auction, Bid, Comment, Watchlist


class create_auction(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'text-center form-control mb-3'
            visible.field.widget.attrs['placeholder'] = visible.field.label
            if 'image_url' in self.fields and isinstance(self.fields['image_url'].widget, forms.Textarea): 
                self.fields['image_url'].widget.attrs['rows'] = 2
            if 'description' in self.fields and isinstance(self.fields['description'].widget, forms.Textarea):
                self.fields['description'].widget.attrs['rows'] = 2     
            

    class Meta:
        model = Auction
        # If we set the exclude fields, it will render evertything but not that ones.
        # fields = '__all__'
        exclude = ['user_owner', 'auction_on', 'date_started']
        widgets = {
            'ending_date': forms.DateInput(attrs={'type': 'date'}),
        }


class submit_bid(forms.Form):
    bid_ammount = forms.FloatField()

views.py (the particular view_listing):

def view_listing(request, id):
    form = submit_bid()
    print(form)
    if request.method == "POST" and form.is_valid:

        pass

    try:
        auction_data = get_object_or_404(Auction, id=id)
    except Http404:
        render (request, 'error_404.html')
    
    # Total number of bids on the listing
    numberof_bids_onlisting = auction_data.bids.count()
    
    # Id of the user if logged_in
    user_logged_id = request.user.id

    # A list of bids on the listing.
    bids = auction_data.bids.values_list('bid', flat=True)
    
    # The current max bid and user id of the bid.
    all_bids_on_listing = auction_data.bids.values('bid', 'user')

    max_bid_info = max(all_bids_on_listing, key=lambda x: x['bid'], default=None)


    user_bid_is_greatest = False
    if request.user.id == max_bid_info['user']:
        # Set it to true if the logged in user is the one that the bid is winning.
        user_bid_is_greatest = True
    
    return render(request, "auctions/view_listing.html", {'auction': auction_data, 'total_bids': numberof_bids_onlisting, 'max_bid_info': max_bid_info, 'user_bid_is_greatest': user_bid_is_greatest,})

Also i leave the template here (view_listing.html):

{% extends "auctions/layout.html" %}

{% block body %}
    <h2 class="view-listing-title">Listing: {{ auction.title }}</h2>
        <div class="container-fluid">
            <div class="view-listing-container container-fluid justify-content-center">
                <a href="/watchlist_add"><span class="badge text-bg-primary ">Watchlist</span></a>
                <img class="img-fluid" src="{{ auction.image_url }}">
            </div>
            <h4>{{ auction.description }}</h3>
            {% if total_bids == None %}
                <h3>${{ auction.starting_price }}</h3>
            {% else %}
                <h3>${{ max_bid_info.bid }}</h3>
            {% endif %}
            {% if request.user.is_authenticated %}
                {% if total_bids == None  %}
                    <p>There is no bid(s) still.</p>
                {% else %}
                    {% if user_bid_is_greatest %}
                        <p>{{ total_bids }} bid(s) so far. Your bid is the current bid.</p>
                    {% else %}
                        <p>{{ total_bids }}bid(s) so far.
                    {% endif %}  
                {% endif %}
                
            <form action="/submit_bid" method="POST">
                {% csrf_token %}
                {{ form.as_p }}
            </form>
            {% else %}
                {% if total_bids == None  %}
                <p>There is no bid(s) still.</p>
                {% else %}
                <p>{{ total_bids }}bid(s) so far.
                {% endif %}
            {% endif %}
            <h3>Details</h3>
            <ul>
                <li>Listed by: {{ auction.user_owner }}</li>
                <li>Category : {{ auction.auction_category }}</li>
            </ul>
        </div>
{% endblock %}

I have to say that the form its imported on the views.py, the url its registered in urls.py. If i pass the argument request to form=submit_bid(request) then when i do print(form) obtain None. I leave here the debugging image of django:

Django error

Thank you in advance guys.


Solution

  • I figured out with help of a great person, Ken. The problem was dummy. The name of the form "submit_bid" (that should need to be SubmitBid), was equal to the name of another view on the project. So that was generating the weird problem. I was calling the view, not the form when instantiating it.