1

I'm trying to call an external api from a class based view. Currently I have the below view which calls the API. However at the moment I am just calling the API with api(username, password) and it returns the data but doesn't save it.

How can I also pass the model used in the modelform in the view to the api function so that it can save the returned data to the relevant user. (ie what method do I need to override in the CBV).

Additional what is the best method for calling an external api in django (to be initiated from a form completion). Currently the API round trip takes 5 -10 secs which at the moment the way it is setup delays the next page load by that amount.

class SupplierOnlineAccountView(CreateView):
    form_class = SupplierOnlineAccountForm
    template_name = 'standard_form.html'
    success_url = '../contacting'

    def form_valid(self, form):
        username = form.cleaned_data.get('username')
        password = form.cleaned_data.get('password')
        api(username, password)
        return super().form_valid(form)

Model:

class EUser(models.Model):
    username = models.CharField(max_length=255, null=True)
    password = models.CharField(max_length=255, null=True)
    address = models.ForeignKey(Address, null=True)
    temp_user = models.CharField(max_length=255, null=True)
    user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, default=None)
    title = models.CharField(max_length=10)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
3
  • Can you elaborate what exactly do you want to do: what data you get, where you want to save it Commented Feb 11, 2016 at 19:34
  • Sure thanks, I'm trying to save the returned api data in Euser model. The SupplierOnlineAccountForm also saves to the Euser model. The Api returns first_name, last_name etc... and other data to be saved in the EUser model. Commented Feb 11, 2016 at 20:03
  • OK, updated an answer. Commented Feb 11, 2016 at 21:05

1 Answer 1

1
def form_valid(self, form):
    username = form.cleaned_data.get('username')
    password = form.cleaned_data.get('password')
    self.object = form.save()
    api(username, password,self.object)
    return super().form_valid(form)

You will have to change the title, first_name, last_name fields to blank=True so you can save before the api call, and then pass the saved model.

The issue of wait time for the API, this is a typical asynchronous task for queue like celery. You save the form, then offload the task to the queue, which runs on another thread (or process, or machine). Then django does not have to wait until the api returns, and sends the response.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, I now see that in the ModelFormMixin. Is there a way not save first but still pass the object to be saved to, like instance = form.save(commit=False) in function based views? I would prefer to avoid putting blank=True in all the fields that the api will save to, as there will likely be a lot in the end.
You can, but it's better to save to db first, especially before it goes to external api.
Just to understand why is it better to save first before going to the api?
Once you off load the api to another thread or queue to save the time, then if the api fails, you still have the object in the DB.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.