简体   繁体   中英

Setting initial field value in generic form through URL parameter

I'm struggling to set an initial value in a form instance based on the URL parameter in Django 3.0.

I have a Claim model:

# models.py

class Claim(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(default=timezone.now)
    member = models.ForeignKey(User, on_delete=models.CASCADE)

I have a NewClaimForm based on ModelForm:

# forms.py

class NewClaimForm(forms.ModelForm):
    class Meta:
        model = Claim
        fields = ['product', 'text']

I have a NewClaimView based on CreateView:

# views.py

class NewClaimView(LoginRequiredMixin, CreateView):
    model = Claim
    form_class = NewClaimForm
    template_name = 'portal/new_claim.html'

    def form_valid(self, form):
        form.instance.member = self.request.user
        return super(NewClaimView, self).form_valid(form)

And using the following template fragment on the index page...

# index.html

    <div class="card-deck">
        {% for product in products %}
            <div class="card text-center">
                <div class="card-header">
                    <h5 class="card-title text-primary">{{ product }}</h5>
                </div>
                <div class="card-body">
                    <ol class="card-text text-left">
                        <li>Fill in the {{ product }} form</li>
                        <li>Attach your medical records</li>
                        <li>Get your claim reviewed within 48 hours</li>
                    </ol>
                    <a href="{% url 'portal:new_claim_product' product_id=product.id %}" class="btn btn-primary">Online Form</a>
                </div>
            </div>
        {% endfor %}
    </div>

...I pass the product_id parameter to the URL:

# urls.py

app_name = 'portal'
urlpatterns = [
    path('new_claim/<int:product_id>/', NewClaimView.as_view(), name='new_claim_product'),
]

And lastly, this is what my new_claim template looks like:

# new_claim.html

{% extends "portal/base.html" %}
{% load bootstrap4 %}

{% block content %}
    <p>Submit a new claim</p>

    <form action="{% url 'portal:new_claim' %}" method='post' class="form" enctype="multipart/form-data">
        {% csrf_token %}
        {% bootstrap_form form %}
        {% buttons %}
            <button name="submit">Submit claim</button>
        {% endbuttons %}
    </form>

{% endblock content %}

I would like to now use the product_id to set the initial value of the product field in the form instance according to product_id . How can I achieve this?

Figured out how to do this by modifying the get method for my class-based view:

# views.py

class NewClaimView(LoginRequiredMixin, CreateView):
    model = Claim
    form_class = NewClaimForm
    template_name = 'portal/new_claim.html'

    def get(self, request, product_id=None, *args, **kwargs):
        form = self.form_class(initial={'product': product_id})
        return render(request, self.template_name, {'form': form})

    def form_valid(self, form):
        form.instance.member = self.request.user
        return super(NewClaimView, self).form_valid(form)

Here's a link to the relevant documentation .

Is this an optimal way to solve this?

Do I need the *args and **kwargs in the modified get method? I'm not using them in my code but perhaps it would be useful to keep them there for other purposes in the future?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM