Django:ManyToMany人口

时间:2014-08-15 13:33:30

标签: python django

我正在研究我的第一个Django应用程序,并希望创建一个脚本来将数据填充到我的模型中以进行测试 - 类似于使用Django处理Tango时所做的那样。 (http://www.tangowithdjango.com/book/chapters/models.html#creating-a-population-script

我知道如何填充大多数模型字段,但是要了解填充ManyToMany字段。最好的方法是什么?

models.py

from django.db import models

# Create your models here.
class Genre(models.Model):
  name = models.CharField(max_length=20, unique=True, blank=False)

  def __unicode__(self):
    return self.name


class Artist(models.Model):
  name = models.CharField(max_length=50, unique=True, blank=False)
  photo = models.ImageField(upload_to='artist_photos', blank=True)
  logo = models.ImageField(upload_to='artist_logos', blank=True)
  genre = models.ManyToManyField(Genre)
  twitter = models.URLField(blank=True)
  facebook = models.URLField(blank=True)
  instagram = models.URLField(blank=True)

  def __unicode__(self):
    return self.name

class Venue(models.Model):
  name = models.CharField(max_length=50, unique=True, blank=False)
  logo = models.ImageField(upload_to='venue_logos', blank=True)
  capacity = models.IntegerField(blank=False)
  address = models.CharField(max_length=50, blank=True)
  city = models.CharField(max_length=50, blank=True)
  state = models.CharField(max_length=50, blank=True)
  zip_code = models.IntegerField(max_length=50, blank=True, null=True)
  website = models.URLField(blank=True)
  twitter = models.URLField(blank=True)
  facebook = models.URLField(blank=True)
  instagram = models.URLField(blank=True)

  def __unicode__(self):
    return self.name

class Show(models.Model):
  venue = models.ForeignKey(Venue)
  date_time = models.DateTimeField(blank=False)
  attendance = models.IntegerField(blank=False)
  bands = models.ManyToManyField(Artist)

populate.py

import os

def populate():
  # Population of genres
  hardcore = add_genre('hardcore')
  poppunk = add_genre('pop-punk')
  indie = add_genre('indie')
  rock = add_genre('rock')
  pop = add_genre('pop')
  rnb = add_genre('rnb')
  hiphop = add_genre('hip-hop')

  # Population of venues
  chain_reaction = add_venue(name='Chain Reaction', cap=400)
  the_observatory = add_venue(name='The Observatory', cap=1500)
  the_glasshouse = add_venue(name='The Glasshouse', cap=700)

  # Population or artists 
  justin_timberlake = add_artist(name='Justin Timberlake', ??????)


def add_genre(name):
  g = Genre.objects.get_or_create(name=name)

def add_venue(name, cap):
  v = Venue.objects.get_or_create(name=name, capacity=cap)

def add_artist(name, genres):
  a = Artist.objects.get_or_create(name=name)

if __name__ == '__main__':
  print 'GOING...'
  os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'artist_database.settings')
  from artistdb.models import Genre, Venue, Artist
  populate()

3 个答案:

答案 0 :(得分:1)

如果要在add_artist函数中添加类型,请将类型作为列表传递,并将它们添加到多对多字段中,如下所示:

def add_artist(name, genres):
  a, created = Artist.objects.get_or_create(name=name)
  for genre in genres:
     a.add(genre)

docs

中的更多信息

答案 1 :(得分:1)

ManyToMany管理员的添加方法可以使用多个模型或ID:

ids_list = [1,2,3]
artist.genre.add(*ids_list) # or
artist.genre.add(1,2,3)

genres_queryset = Genre.objects.filter(name__in=[genres])
artist.genre.add(*genres_queryset)

所以你可以改写你的方法:

def add_artist(name, genres):
  a, created = Artist.objects.get_or_create(name=name)
  a.genre.add(*Genre.objects.filter(name__in=[genres]))

答案 2 :(得分:0)

您应该阅读fixtures上的文档,因为您不需要使用脚本执行此操作。从文档中添加一个名为m2m的多对多字段,如下所示:

[
  {
    "model": "myapp.person",
    "pk": 1,
    "fields": {
      "first_name": "John",
      "last_name": "Lennon"
      "m2m": [1,2]
    }
  },
  {
    "model": "myapp.person",
    "pk": 2,
    "fields": {
      "first_name": "Paul",
      "last_name": "McCartney"
      "m2m": [1,2]
    }
  }
]

您会看到m2m字段只是将主键列表作为参数。