1

私は次のモデルを持っています:

class Car(models.Model):
 id = models.AutoField(primary_key=True)
 slug = models.CharField(max_length=128L, unique=True, blank=True)
 name = models.CharField(max_length=128L, blank=True)
 model_slug = models.CharField(max_length=128L, unique=True, blank=True)
 ...

CarXML ファイルからのリストを取得しているときはいつでも、それらのいくつかは
(同じスラグで) 複数回表示されます。それを保存しようとすると、
IntegrityError(1062, "Duplicate entry 'car-slug' for key 'slug'")

重複エラーが発生した場合に備えて、既存の Car をロードする (または更新する、どちらか簡単な方) ようにします。
しかし、model_slug (またはそのエラーを生成する一意のフィールド) で機能するように、十分に一般的なものにしたいと考えています。

4

3 に答える 3

2

必要なものget_or_create:

car,created = Car.objects.get_or_create(slug='car-slug')
if created:
   print 'New car was created'
   car.slug = 'new-car-slug'
else:
   # do whatever needs to be done here
   # with the existing car object, which will
   # be car
   # car.name = 'new name'

car.save()

に提供する引数に関係なくget_or_create、それらを使用してモデルの既存のレコードを検索します。


どのフィールドの組み合わせが重複をトリガーするかわからないとします。簡単な方法は、モデル内のどのフィールドにその制限があるか (つまりunique=True) を見つけることです。モデルからこの情報を内省できます。または、より簡単な方法は、単にこれらのフィールドを に渡すことget_or_createです。

最初のステップは、XML フィールドとモデルのフィールドの間のマッピングを作成することです。

xml_lookup = {}
xml_lookup = {'CAR-SLUG': 'slug'}  # etc. etc.

必要に応じて、これをすべてのフィールドに入力できますが、一意の制約があるフィールドのみを入力することをお勧めします。

次に、XML を解析している間に、レコードごとに辞書を作成し、各フィールドをマッピングします。

for row in xml_file:
    lookup_dict = {}
    lookup_dict[xml_lookup[row['tag']] = row['value']  # Or something similar
    car, created = Car.objects.get_or_create(**lookup_dict)
    if created:
       # Nothing matched, a new record was created
       # Any any logic you need here
    else:
       # Existing record matched the search parameters
       # Change/update whatever field to prevent the IntegrityError
       car.model_slug = row['MODEL_SLUG']
       # Set/update fields as required
    car.save()  # Save the modified object
于 2013-05-26T09:37:26.800 に答える
0

モデルにカスタム保存を作成することになりました(コードが変更されないように、モデルだけが変更されます):

def save(self, *args, **kwargs):
    try:
        super(Car, self).save(*args, **kwargs)
    except IntegrityError, e:
        existing_object = Car.objects.get(slug=self.slug)
        self = existing_object
        super(Car, self).save(*args, **kwargs)
        return existing_object.id

ここで、オブジェクトの ID を返して割り当てるため、save() コマンドは次のようになります。

the_id = generic_object.save() #e.g. Car
if the_id:
    generic_object.id = the_id
于 2013-05-31T07:32:54.830 に答える
0

最初にメモリ内の重複する車のエントリをフィルタリングしてから、新しいアイテムで create を呼び出すことができます。

uniq_attrs = ['slug', 'model_slug', ...]
existed_attrs = set()
for car in car_list:
    # skip the duplicates
    if any([(attr, car[attr]) in existed_attrs for attr in uniq_attrs):
        continue
    uniq_attrs.update([(attr, car[attr]) for attr in uniq_attrs])

    # save the new car to db
    Car.objects.save(....)

または、一意のフィールドで get_or_create を試してから、モデルの保存で他の属性を保存できます。

for car in car_list:
    attr_dict = {attr:car[attr] for attr in uniq_attrs}
    car, created = Car.objects.get_or_create(**attr_dict)

    # already created before
    if created:
        continue

    # save other attributes
    car.set(...)
    car.set(...)
    car.save()
于 2013-05-26T12:04:23.603 に答える