Home > Back-end >  How to set html attributes to Django form created using model
How to set html attributes to Django form created using model

Time:01-06

I have model

class Listings(models.Model):
    user_id = models.ForeignKey(
        User,
        on_delete=models.CASCADE
    )
    title = models.CharField(max_length=180)
    desc = models.CharField(max_length=900)
    price = models.IntegerField(validators=[MinValueValidator(1)])
    img = models.ImageField(upload_to='uploads')
    timestamp = models.DateTimeField(auto_now_add=True)

And form class

class ListingForm(ModelForm):
    class Meta:
        model = Listings
        fields = ('title', 'category', 'price', 'desc', 'img')
        labels = {
            'desc': 'Description',
            'img': 'Upload photo',
            'price': 'Starting price'
        }

I want to add HTML attributes like min="0" or remove required from my img = models.ImageField(upload_to='uploads') for example. How can I implement this?

I found in stack overflow method with widgets = {'price': IntegerField(attrs='min': 0}) and I also tried ...forms.IntegerField... but I had

TypeError: __init__() got an unexpected keyword argument 'attrs'

And I also found solution with

def __init__(self, *args, **kwargs):
    super(Listings, self).__init__(*args, **kwargs)
    self.fields['price'].widget.attrs.update({
        'min': 1
    })

(I added it to my form class)

But also did not work

super(Listings, self).__init__(*args, **kwargs)
TypeError: super(type, obj): obj must be an instance or subtype of type
[05/Jan/2023 19:22:01] "GET /create_listing HTTP/1.1" 500 60691

CodePudding user response:

An IntegerField [Django-doc] is not a widget, but a form field. The default widget for an IntegerField is a NumberInput [Django-doc]:

class ListingForm(ModelForm):
    class Meta:
        model = Listings
        fields = ('title', 'category', 'price', 'desc', 'img')
        labels = {
            'desc': 'Description',
            'img': 'Upload photo',
            'price': 'Starting price',
        }
        widget = {'price': forms.NumberInput(attrs={'min': 0})}

or you can work with:

class ListingForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['price'].widget.attrs['min'] = 1

    class Meta:
        model = Listings
        fields = ('title', 'category', 'price', 'desc', 'img')
        labels = {
            'desc': 'Description',
            'img': 'Upload photo',
            'price': 'Starting price',
        }

CodePudding user response:

In case it will be useful for someone. You should place (in my case)

class ListingForm(ModelForm):
    price = forms.IntegerField(widget=forms.NumberInput(
        attrs={
            'min': 0
        }))
    desc = forms.CharField(widget=forms.Textarea(
        attrs={
            'placeholder': 'Enter your description',
        }))
    img = forms.ImageField(widget=forms.FileInput(
        attrs={
            'id': 'img'
        }
    ))
    class Meta:
    # and code from question

And if you need to remove required from any field, you can add

    <script>
        document.getElementById("img").required = false;
    </script>

To your html file

  • Related