2011-05-24 22 views
9

Benim modelleri: admin.py olarakDjango - admin UserProfile m2m alan - Hata

class UserProfile(models.Model): 
    TYPES_CHOICES = (
     (0, _(u'teacher')), 
     (1, _(u'student')), 
    ) 
    user = models.ForeignKey(User, unique=True) 
    type = models.SmallIntegerField(default=0, choices=TYPES_CHOICES, db_index=True) 
    cities = models.ManyToManyField(City) 
class City(models.Model): 
    name = models.CharField(max_length=50) 
    slug = models.SlugField(max_length=50) 

:

admin.site.unregister(User) 
class UserProfileInline(admin.StackedInline): 
    model = UserProfile 

class UserProfileAdmin(UserAdmin): 
    inlines = [UserProfileInline] 

admin.site.register(User, UserProfileAdmin) 

@receiver(post_save, sender=User) 
def create_profile(sender, instance, created, **kwargs): 
    """Create a matching profile whenever a user object is created.""" 
    if created: 
     profile, new = UserProfile.objects.get_or_create(user=instance) 

Ama yeni kullanıcı eklemek ve bir şehir seçtiğinizde o hata alıyorum: IntegrityError/admin/auth/kullanıcı/add/ (1062, "Anahtar 'user_id' için giriş '3' ')

Kodumda sorun mu var? Herhangi bir şehir seçmezsem - kullanıcı düzgün eklenir. Bir şekilde, kullanıcı UserProfile'a bir kereden fazla ekleniyor.

cevap

20

Son zamanlarda aynı sorunu yaşadım. Bunu düşündüğünüzde aslında mükemmel bir anlam ifade eder. Bir formu yönetici içinde satır içi ile kaydettiğinizde, önce ana modeli kaydeder ve ardından her satır içi kaydetmeye devam eder. Modeli kaydettiğinde, post_save sinyaliniz kesilir ve eşleşmesi için bir UserProfile oluşturulur, ancak şimdi satır içi kaydetme zamanı. UserProfile satır içi yeni kabul edilir, çünkü daha önce var olmadı (pk değeri yoktur), bu yüzden tamamen yeni ve farklı bir UserProfile olarak kaydetmeye çalışır ve benzersiz kısıtlamayı ihlal etmek için bu bütünlük hatasını alırsınız. Çözüm basit. Sadece UserProfile.save geçersiz: Söz konusu kullanıcı için mevcut bir UserProfile varsa

def save(self, *args, **kwargs): 
    if not self.pk: 
     try: 
      p = UserProfile.objects.get(user=self.user) 
      self.pk = p.pk 
     except UserProfile.DoesNotExist: 
      pass 

    super(UserProfile, self).save(*args, **kwargs) 

Esasen, bu sadece denetler. Eğer öyleyse, bu UserProfile'ın pk'sini, Django'nun bir yaratım yerine bir güncelleme yapmasını sağlayacak şekilde ayarlar.

+0

Teşekkürler, şimdi çalışıyor! Çok basit bir btw: D – robos85

+0

Teşekkürler! Bende aynı sorun vardı. Bu çözüm mantıklı ve mükemmel çalıştı. – adam

+2

Mükemmel bir şekilde açıkladı. Belki de ek kullanıcı verilerinin saklanmasıyla ilgili Django dokümantasyonu, dokümantasyonda sunulan örneklerin aksini göstermediği için bunu belirtmek için güncellenmelidir. – CadentOrange