Join two QuerySet of different models in Django

1

I am trying to make a query to two different models, which have a common field. This is my file models.py :

class Service(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    # otros atributos

class Visa(models.Model):
    # atributos de la clase Visa


class Passport(models.Model):
    # atributos de la clase Passport

and in the view I have ( views.py ):

class SearchView(generic.FormView):
    form_class = forms.SearchForm
    # otros atributos

    def form_valid(self, form):
        search = form.search_status()
        if self.request.is_ajax():
            data = {
                'data': search,
            }
            return JsonResponse(data)
        else:
            return super().form_valid(form)

And this is my file forms.py :

class SearchForm(forms.Form):
    search = forms.CharField()

    def search_status(self):
        search = self.cleaned_data['search']
        visa_result = models.Visa.objects.filter(
            Q(client__ci__exact=search) & Q(status='active')
        )
        passport_result = models.Passport.objects.filter(
            Q(client__ci__exact=search) & Q(status='active')
        )
        result = []
        for v in visa_result:
            result.append(v)
        for p in passport_result:
            result.append(p)
        return result

The query performs well, but on the visa, when a json returns, it gives the following error: TypeError: Object of type 'Visa' is not JSON serializable . How can I make my models serializable?

    
asked by Reinier Hernández Ávila 13.12.2018 в 18:13
source

1 answer

0

There are some fields in the models that can not be serialized by default, for that you need special encoders as mentioned in the comments but in my opinion they are a bit limited.

I see that you only call the search_status function when it is AJAX so this should suffice:

class SearchForm(forms.Form):
    search = forms.CharField()

    def search_status(self):
        search = self.cleaned_data['search']
        visa_result = models.Visa.objects.filter(
            Q(client__ci__exact=search) & Q(status='active')
        )
        passport_result = models.Passport.objects.filter(
            Q(client__ci__exact=search) & Q(status='active')
        )
        result = []
        for v in visa_result:
            # Los campos que necesites
            result.append({
                'v_id': v.id,
                'v_otro_campo': v.otro_campo,
                'v_relacion_id': v.relacion.id # una relación a otro modelo
                'v_relacion_nombre': v.relacion.nombre # la misma relación, otro campo
            })

        for p in passport_result:
            # Los campos que necesites
            result.append({
                'p_id': p.id,
                'p_otro_campo': p.otro_campo
            })
        return result

Now when calling the function from your view there should be no problems. You probably need to modify the function that is receiving these fields to use the correct names ( p_id , v_id , etc.).

The function you receive from JsonResponse should see something like this:

[
    {"v_id": 1, "v_otro_campo": "foo", "v_relacion_id": 5, "v_relacion_nombre": "Mr. Foo"},
    {"p_id": 100, "p_otro_campo": "bar"},
    ...
]
    
answered by 14.12.2018 в 17:19