Question

I have multiple models that are associated by Foreign Keys. I can export them all separately using django rest framework on a one to one basis, and I can also export multiple ones nested. However I want to be able to essentially "concatenate" them together into a single json/xml export.

The models in the example below are joined by a one to one foreign key on jobdtl_id. I have some where it's one to many but I'm hoping I can figure that out when I know how to get a view that will link 2 separate models like I want below -

Here's an example of what I want the json to look like by hitting a single URL like

http://localhost/job/4/

{
  "job": {
    "-id": "9878",
    "-name": "This is the job",
    "-master": "blahserver",
    "-dbversion": "234",
    "-xmlversion": "1",
    "jobmst": {
      "jobmst_id": "9878",
      "jobmst_type": "2",
      "jobmst_prntid": "234",
      "jobmst_active": "Y",
      "jobmst_name": "This is the job",
      "jobmst_owner": "Owner",
      "jobdtl_id": "9878",
      "jobmst_lstchgtm": {
        "-date": "Y",
        "#text": "2013-10-23 09:22:08.0"
      },
      "jobmst_prntname": "Parent",
      "jobmst_alias": "9878"
    },
    "jobdtl": {
      "jobdtl_id": "9878",
      "jobdtl_cmd": "blah.exe",
      "jobdtl_failalarm": "NULL",
      "nodmst_id": "NULL",
      "nodlstmst_id": "NULL",
      "jobdtl_inhevent": "Y",
      "jobdtl_inhoptions": "Y",
      "jobdtl_inhagent": "Y",
      "jobdtl_inhrepeat": "Y",
      "jobdtl_inhtime": "Y",
      "jobdtl_timewin": "NULL",
      "jobdtl_saveoutput": "Y",
      "jobdtl_outputname": "NULL",
      "jobdtl_trackmethod": "1",
      "jobdtl_trackcmd": "NULL",
      "jobdtl_deplogic": "1",
      "jobdtl_rerun": "NULL",
      "jobdtl_params": "--blah --ok"
    },
    "jobdep": [
      {
        "jobdep_id": "79670",
        "jobmst_id": "9878",
        "jobdep_type": "1",
        "jobdep_jobmst": "another job",
        "varmst_id": "NULL"
      },
      {
        "-num": "2",
        "jobdep_id": "83783",
        "jobmst_id": "9878",
        "jobdep_type": "1",
        "jobdep_jobmst": "and another",
        "varmst_id": "NULL"
      }
    ],
    "trgjob": [
      {
        "trgjob_id": "22286",
        "trgmst_id": "23455",
        "jobmst_id": "9878"
      },
      {
        "-num": "2",
        "trgjob_id": "28980",
        "trgmst_id": "23521",
        "jobmst_id": "9878"
      },
      {
        "-num": "3",
        "trgjob_id": "28981",
        "trgmst_id": "9237",
        "jobmst_id": "9878"
      }
    ]
  }
}

The models are basically like this -

class Jobdtl(models.Model):
    jobdtl_id = models.IntegerField(primary_key=True)
    jobdtl_cmd = models.TextField(blank=True)
    ....
    jobdtl_duration = models.IntegerField(blank=True, null=True)
    class Meta:
        managed = False
        db_table = 'jobdtl'

class Jobmst(models.Model):
    jobmst_id = models.IntegerField(primary_key=True)
    jobmst_type = models.SmallIntegerField()
    ....
    jobdtl_id = models.ForeignKey('Jobdtl', db_column='jobdtl_id', related_name='mstdtl', blank=True, null=True)
    def __unicode__(self):
        return self.jobmst_name   
    class Meta:
        managed = False
        db_table = 'jobmst'

end caveat I'm converting the json from how the XML looks for the existing legacy app which is like so -

<?xml version="1.0"?>
<job id="9878" name="This is the job" master="blahserver" dbversion="532" xmlversion="1">
    <jobmst>
        <jobmst_id>9878</jobmst_id>
        <jobmst_type>2</jobmst_type>
        <jobmst_prntid>234</jobmst_prntid>
        <jobmst_active>Y</jobmst_active>
        <jobmst_name>This is the job</jobmst_name>
        <jobmst_owner>Owner</jobmst_owner>
        <jobdtl_id>9878</jobdtl_id>
        <jobmst_lstchgtm date="Y">2013-10-23 09:22:08.0</jobmst_lstchgtm>
        <jobmst_prntname>Parent</jobmst_prntname>
        <jobmst_alias>9878</jobmst_alias>
    </jobmst>
    <jobdtl>
        <jobdtl_id>9878</jobdtl_id>
        <jobdtl_cmd>blah.exe</jobdtl_cmd>
        <jobdtl_failalarm>NULL</jobdtl_failalarm>
        <nodmst_id>NULL</nodmst_id>
        <nodlstmst_id>NULL</nodlstmst_id>
        <jobdtl_inhevent>Y</jobdtl_inhevent>
        <jobdtl_inhoptions>Y</jobdtl_inhoptions>
        <jobdtl_inhagent>Y</jobdtl_inhagent>
        <jobdtl_inhrepeat>Y</jobdtl_inhrepeat>
        <jobdtl_inhtime>Y</jobdtl_inhtime>
        <jobdtl_timewin>NULL</jobdtl_timewin>
        <jobdtl_saveoutput>Y</jobdtl_saveoutput>
        <jobdtl_outputname>NULL</jobdtl_outputname>
        <jobdtl_trackmethod>1</jobdtl_trackmethod>
        <jobdtl_trackcmd>NULL</jobdtl_trackcmd>
        <jobdtl_deplogic>1</jobdtl_deplogic>
        <jobdtl_rerun>NULL</jobdtl_rerun>
        <jobdtl_params>--blah --ok</jobdtl_params>
    </jobdtl>
    <jobdep>
        <jobdep_id>79670</jobdep_id>
        <jobmst_id>9878</jobmst_id>
        <jobdep_type>1</jobdep_type>
        <jobdep_jobmst>another job</jobdep_jobmst>
        <varmst_id>NULL</varmst_id>
    </jobdep>
    <jobdep num="2">
        <jobdep_id>83783</jobdep_id>
        <jobmst_id>9878</jobmst_id>
        <jobdep_type>1</jobdep_type>
        <jobdep_jobmst>and another</jobdep_jobmst>
        <varmst_id>NULL</varmst_id>
    </jobdep>
    <trgjob>
        <trgjob_id>22286</trgjob_id>
        <trgmst_id>23455</trgmst_id>
        <jobmst_id>9878</jobmst_id>
    </trgjob>
    <trgjob num="2">
        <trgjob_id>28980</trgjob_id>
        <trgmst_id>23521</trgmst_id>
        <jobmst_id>9878</jobmst_id>
    </trgjob>
    <trgjob num="3">
        <trgjob_id>28981</trgjob_id>
        <trgmst_id>9237</trgmst_id>
        <jobmst_id>9878</jobmst_id>
    </trgjob>
</job>
Était-ce utile?

La solution 2

I found the solution by doing the following in my views.py

...
@csrf_exempt        
def tesxml_test(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        mst = Jobmst.objects.using('database1').get(jobmst_id=pk)
        dtl = Jobdtl.objects.using('database1').get(jobdtl_id=pk)
        dep = Jobdep.objects.using('database2').filter(jobmst_id=pk).order_by('jobdep_id')
        trg = Trgjob.objects.using('database1').filter(jobmst_id=pk).order_by('trgjob_order')
    except Jobmst.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        #Get String Results of 4 queries
        jobmststring = JobmstSerializer(mst)
        jobdtlstring = JobdtlSerializer(dtl)
        jobdepstring = JobdepSerializer(dep)
        trgjobstring = TrgjobSerializer(trg)
        #Get serialized Results of 4 queries
        jobmst_serialized = {'jobmst': jobmststring.data}
        jobdtl_serialized = {'jobdtl': jobdtlstring.data}
        jobdep_serialized = {'jobdep': jobdepstring.data}
        trgjob_serialized = {'trgjob': trgjobstring.data}

        jobgroup = jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized,


        jobgroupresponse = TESXMLResponse(jobgroup)
        return jobgroupresponse
...

It's not perfect but it puts me on the next step of my problem which is customizing the renderer to get the data in the root fields which I have another SO question for :)

Autres conseils

class MSTSerializer(serializers.HyperlinkedModelSerializer):
    jobdtl_id = DTLSerializer()
    class Meta:
        model = Jobmst
        fields = ('id', 'url', 'jobdtl_id'...)

class DTLSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Jobdtl
        fields = ('id', 'url',  ...)

Would result in a more correct data structure of

{
    "jobmst_id": 4,
    "jobmst_type": 1,
    "jobdtl_id": {
       "jobdtl_id": 4,
       "jobdtl_cmd": null,
       "jobdtl_duration": 1379
    },

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top