0

I am making an auction site. I need to know per listing who the creator was (so the creators will have the possibility to delete the listing). It works for me to manually change the user in Django Admin, but I want it to be automatically saved when someone creates a new listing.

How do I pass the creator of a form to the form?

These are the relevant models:

class User(AbstractUser):
    pass

class AuctionListing(models.Model):
    title = models.CharField(max_length=64)
    description = models.CharField(max_length=512, default="")
    starting_bid = models.DecimalField(max_digits=6, decimal_places=2, default=0.01, validators=[MinValueValidator(Decimal('0.01'))])
    url = models.URLField(max_length=200, blank=True)
    category = models.CharField(max_length = 20)
    user = models.ForeignKey(User, on_delete=models.CASCADE, db_constraint=False, related_name="items")
    def __str__(self):
        return self.title

Here is my forms.py:

class CreateListing(forms.ModelForm):
    category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
    class Meta:
        model = AuctionListing
        fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
        widgets = {
            'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
            'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
            'user': forms.HiddenInput(),
        }

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super().__init__(*args, **kwargs)
       
        self.fields['user'].initial = user.id

And here was my attempt for the view:

def create_listing(request):
    form = CreateListing(request.POST, user=request.user)
    if request.method == "POST":
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse("index"))
        else:
            print("RIP")
            return render(request, "auctions/create_listing.html", {"form": form})
    return render(request, "auctions/create_listing.html", {
        "form" : CreateListing(user=request.user)
    })

auctions/create_listing.html looks like this:

<h1> Create new listing </h1>
<form action="" method="POST">
    {% csrf_token %}
        <label>Name*</label>
        <br>
        {{ form.title }}
    <br>
        <label >Description*</label>
        <br>
        {{ form.description }}
        <br>   
        <label >Starting bid*</label>
        <br>
        {{ form.starting_bid }}
        <br>  
        <label > Image url (optional) </label>
        <br>
        {{ form.url }}
        <br>  
        <label > Category (optional) </label>
        <br>
        {{ form.category }}
        <br> 
        {{ form.user }}
        <button type="submit" class="btn btn-primary save">Create your listing</button>
    
</form>

The error I get with this is: "BaseModelForm.init() got an unexpected keyword argument 'user'"

How can I fix this so the user will automatically be saved each time a listing is created?

Annelotte
  • 75
  • 7
  • 1
    Does this answer your question? [how to do i automatically set the user field to current user in django modelform](https://stackoverflow.com/questions/46940623/how-to-do-i-automatically-set-the-user-field-to-current-user-in-django-modelform) also [How do I set user field in form to the currently logged in user?](https://stackoverflow.com/questions/18246326/how-do-i-set-user-field-in-form-to-the-currently-logged-in-user) – Abdul Aziz Barkat Aug 16 '22 at 12:12

2 Answers2

1

Add user argument in the __init__ method of the form. You can set the user right there and there is no need for even displaying the user field. You can completely hide it.

class CreateListing(forms.ModelForm):
    category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
    class Meta:
        model = AuctionListing
        fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
        widgets = {
            'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
            'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
            'user': forms.HiddenInput(),
        }

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super().__init__(*args, **kwargs)
       
        self.fields['user'].initial = user.id

Remember to use the user kwarg in the view:

def create_listing(request):
    form = CreateListing(request.POST, user=request.user)
    if request.method == "POST":
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse("index"))
        else:
            print("RIP")
            # If form is invalid you should render the same template again
            # with the errors
            return render(request, "auctions/create_listing.html", {"form": form})
    return render(request, "auctions/create_listing.html", {
        # For the empty form, this needs to be an instance of the form,
        # and not a class
        "form" : CreateListing(user=request.user)
    })

Also, you can replace your HTML with:

{{ form.user }}
vinkomlacic
  • 1,822
  • 1
  • 9
  • 19
0

Replace {{ form.user }} by <input type="hidden" name="user" value="{{request.user}}">

User has to come automatically so you don't need to display user field in the front-end

by the above method you'll get logged in user but still hard to save as it is foreign key, what ever you get from front-end it'll be string type.

So best suggestion is the below code.

    if form.is_valid():
        form_data = form.save()
        form_data.user = request.user
        form_data.save()
Ibrahim Khan
  • 184
  • 10
  • Hey, thanks for your answer. I made your suggested edits but now my form isn't valid when I submit it. Is there something I need to change in my CreateListing form? – Annelotte Aug 16 '22 at 12:49