2013-03-20 65 views
0
檢索最後插入的主鍵

我建立與GeoDjango內置的應用程序,我有以下問題:GeoDjango內置:從LayerMapping

我需要從一個GPX文件中讀取的軌道數據,並將這些數據應該存儲在一個模型MultiLineStringField領域。 這應該在管理界面,用戶上傳

我試圖做到這一點,即數據從應分配給MultiLineStringField文件抓起一個GPX文件發生,而其他領域應該得到的值表格。

我的模式是:

class GPXTrack(models.Model): 
    nome = models.CharField("Nome", blank = False, max_length = 255) 
    slug = models.SlugField("Slug", blank = True) 
    # sport natura arte/cultura 
    tipo = models.CharField("Tipologia", blank = False, max_length = 2, choices=TIPOLOGIA_CHOICES) 
    descrizione = models.TextField("Descrizione", blank = True) 

    gpx_file = models.FileField(upload_to = 'uploads/gpx/') 
    track = models.MultiLineStringField(blank = True) 
    objects = models.GeoManager() 
    published = models.BooleanField("Pubblicato") 
    rel_files = generic.GenericRelation(MyFiles) 
    #publish_on = models.DateTimeField("Pubblicare il", auto_now_add = True) 

    created = models.DateTimeField("Created", auto_now_add = True) 
    updated = models.DateTimeField("Updated", auto_now = True) 

    class Meta: 
     #verbose_name = "struttura'" 
     #verbose_name_plural = "strutture" 
     ordering = ['-created'] 

    def __str__(self): 
     return str(self.nome) 

    def __unicode__(self): 
     return '%s' % (self.nome) 

    def put(self): 
     self.slug = sluggy(self.nome) 

     key = super(Foresta, self).put() 
     # do something after save 
     return key 

而在admin.py文件我已覆蓋保存方法如下:

from django.contrib.gis import admin 
from trails.models import GPXPoint, GPXTrack 
from django.contrib.contenttypes import generic 
from django.contrib.gis.gdal import DataSource 
#from gpx_mapping import GPXMapping 
from django.contrib.gis.utils import LayerMapping 
from django.template import RequestContext 
import tempfile 
import os 
import pprint 

class GPXTrackAdmin(admin.OSMGeoAdmin): 
    list_filter = ('tipo', 'published') 
    search_fields = ['nome'] 
    list_display = ('nome', 'tipo', 'published', 'gpx_file') 
    inlines = [TrackImagesInline, TrackFilesInline] 
    prepopulated_fields = {"slug": ("nome",)} 

    def save_model(self, request, obj, form, change): 
     """When creating a new object, set the creator field. 
     """ 
     if 'gpx_file' in request.FILES: 
      # Get 
      gpxFile = request.FILES['gpx_file'] 
      # Save 
      targetPath = tempfile.mkstemp()[1] 
      destination = open(targetPath, 'wt') 
      for chunk in gpxFile.chunks(): 
       destination.write(chunk) 
      destination.close() 

      #define fields of interest for LayerMapping 
      track_point_mapping = {'timestamp' : 'time', 
            'point' : 'POINT', 
          } 

      track_mapping = {'track' : 'MULTILINESTRING'} 

      gpx_file = DataSource(targetPath) 
      mytrack = LayerMapping(GPXTrack, gpx_file, track_mapping, layer='tracks') 
      mytrack.save() 

      #remove the temp file saved 
      os.remove(targetPath) 
      orig = GPXTrack.objects.get(pk=mytrack.pk) 
      #assign the parsed values from LayerMapping to the appropriate Field 
      obj.track = orig.track 
      obj.save() 

據我所知:

  1. LayerMapping不能用於更新字段,但僅用於保存新字段
  2. I (在上面的代碼,即:mytrack.track)不能訪問LayerMapping對象的特定字段,其值分配到模型字段(即obj.track)在model_save方法
  3. 我不能檢索主最後保存LayerMapping對象的鍵(即在上面的代碼:mytrack.pk),以便與在LayerMapping.mapping

沒有映射的形式爲現場傳遞的值來更新它我能那麼呢?!?!

回答

0

我對它進行了分類,然後添加一個方法get_values()來代替保存檢索到的數據,並返回它們以供任何使用或操作。get_values方法是LayerMapping::save()方法的副本,它返回值而不是保存他們。 我使用Django 1.5

import os 
from django.contrib.gis.utils import LayerMapping 
import sys 
class MyMapping(LayerMapping): 
    def get_values(self, verbose=False, fid_range=False, step=False, 
     progress=False, silent=False, stream=sys.stdout, strict=False): 
     """ 
     Returns the contents from the OGR DataSource Layer 
     according to the mapping dictionary given at initialization. 

     Keyword Parameters: 
     verbose: 
      If set, information will be printed subsequent to each model save 
      executed on the database. 

     fid_range: 
      May be set with a slice or tuple of (begin, end) feature ID's to map 
      from the data source. In other words, this keyword enables the user 
      to selectively import a subset range of features in the geographic 
      data source. 

     step: 
      If set with an integer, transactions will occur at every step 
      interval. For example, if step=1000, a commit would occur after 
      the 1,000th feature, the 2,000th feature etc. 

     progress: 
      When this keyword is set, status information will be printed giving 
      the number of features processed and sucessfully saved. By default, 
      progress information will pe printed every 1000 features processed, 
      however, this default may be overridden by setting this keyword with an 
      integer for the desired interval. 

     stream: 
      Status information will be written to this file handle. Defaults to 
      using `sys.stdout`, but any object with a `write` method is supported. 

     silent: 
      By default, non-fatal error notifications are printed to stdout, but 
      this keyword may be set to disable these notifications. 

     strict: 
      Execution of the model mapping will cease upon the first error 
      encountered. The default behavior is to attempt to continue. 
     """  
      # Getting the default Feature ID range. 
     default_range = self.check_fid_range(fid_range) 

     # Setting the progress interval, if requested. 
     if progress: 
      if progress is True or not isinstance(progress, int): 
       progress_interval = 1000 
      else: 
       progress_interval = progress 

     # Defining the 'real' save method, utilizing the transaction 
     # decorator created during initialization. 
     @self.transaction_decorator 
     def _get_values(feat_range=default_range, num_feat=0, num_saved=0): 
      if feat_range: 
       layer_iter = self.layer[feat_range] 
      else: 
       layer_iter = self.layer 

      for feat in layer_iter: 
       num_feat += 1 
       # Getting the keyword arguments 
       try: 
        kwargs = self.feature_kwargs(feat) 
       except LayerMapError, msg: 
        # Something borked the validation 
        if strict: raise 
        elif not silent: 
         stream.write('Ignoring Feature ID %s because: %s\n' % (feat.fid, msg)) 
       else: 
        # Constructing the model using the keyword args 
        is_update = False 
        if self.unique: 
         # If we want unique models on a particular field, handle the 
         # geometry appropriately. 
         try: 
          # Getting the keyword arguments and retrieving 
          # the unique model. 
          u_kwargs = self.unique_kwargs(kwargs) 
          m = self.model.objects.using(self.using).get(**u_kwargs) 
          is_update = True 

          # Getting the geometry (in OGR form), creating 
          # one from the kwargs WKT, adding in additional 
          # geometries, and update the attribute with the 
          # just-updated geometry WKT. 
          geom = getattr(m, self.geom_field).ogr 
          new = OGRGeometry(kwargs[self.geom_field]) 
          for g in new: geom.add(g) 
          setattr(m, self.geom_field, geom.wkt) 
         except ObjectDoesNotExist: 
          # No unique model exists yet, create. 
          m = self.model(**kwargs) 
        else: 
         m = self.model(**kwargs) 

        try: 
         # Attempting to save. 
         pippo = kwargs 

         num_saved += 1 
         if verbose: stream.write('%s: %s\n' % (is_update and 'Updated' or 'Saved', m)) 
        except SystemExit: 
         raise 
        except Exception, msg: 
         if self.transaction_mode == 'autocommit': 
          # Rolling back the transaction so that other model saves 
          # will work. 
          transaction.rollback_unless_managed() 
         if strict: 
          # Bailing out if the `strict` keyword is set. 
          if not silent: 
           stream.write('Failed to save the feature (id: %s) into the model with the keyword arguments:\n' % feat.fid) 
           stream.write('%s\n' % kwargs) 
          raise 
         elif not silent: 
          stream.write('Failed to save %s:\n %s\nContinuing\n' % (kwargs, msg)) 

       # Printing progress information, if requested. 
       if progress and num_feat % progress_interval == 0: 
        stream.write('Processed %d features, saved %d ...\n' % (num_feat, num_saved)) 

      # Only used for status output purposes -- incremental saving uses the 
      # values returned here. 
      return pippo 

     nfeat = self.layer.num_feat 
     if step and isinstance(step, int) and step < nfeat: 
      # Incremental saving is requested at the given interval (step) 
      if default_range: 
       raise LayerMapError('The `step` keyword may not be used in conjunction with the `fid_range` keyword.') 
      beg, num_feat, num_saved = (0, 0, 0) 
      indices = range(step, nfeat, step) 
      n_i = len(indices) 

      for i, end in enumerate(indices): 
       # Constructing the slice to use for this step; the last slice is 
       # special (e.g, [100:] instead of [90:100]). 
       if i + 1 == n_i: step_slice = slice(beg, None) 
       else: step_slice = slice(beg, end) 

       try: 
        pippo = _get_values(step_slice, num_feat, num_saved) 
        beg = end 
       except: 
        stream.write('%s\nFailed to save slice: %s\n' % ('=-' * 20, step_slice)) 
        raise 
     else: 
      # Otherwise, just calling the previously defined _save() function. 
      return _get_values() 

在自定義保存或可以save_model方法,然後使用:

 track_mapping = {'nome': 'name', 
         'track' : 'MULTILINESTRING'} 

     targetPath = "/my/gpx/file/path.gpx" 
     gpx_file = DataSource(targetPath) 

     mytrack = MyMapping(GPXTrack, gpx_file, track_mapping, layer='tracks') 

     pippo = mytrack.get_values() 
     obj.track = pippo['track']