我有一个像这样的django模型:
class Something(models.Model):
title = models.CharField(max_length=200, default=u'')
text = models.CharField(max_length=250, default=u'', blank=True)
photo = models.ImageField(upload_to=u'something')
def photo_thumb(self):
if self.photo:
return u'<img src="%s" />' % (settings.MEDIA_URL + '/thumbs/?h=64&w=80&c=50x0&p=' + self.photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
def __unicode__(self):
return self.title;
class SomethingElse(models.Model):
name = models.CharField(max_length=200, default=u'')
foo = models.CharField(max_length=250, default=u'', blank=True)
photo = models.ImageField(upload_to=u'something_else')
def photo_thumb(self):
if self.photo:
return u'<img src="%s" />' % (settings.MEDIA_URL + '/thumbs/?h=64&w=80&c=50x0&p=' + self.photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
def __unicode__(self):
return self.title;
我觉得这样做违反DRY,原因很明显。我的问题是,我可以把它贴在其他地方:
# ...
def photo_thumb(self):
if self.photo:
return u'<img src="%s" />' % (settings.MEDIA_URL + '/thumbs/?h=64&w=80&c=50x0&p=' + self.photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
# ...
然后用一行代码将它包含在相关的模型类中?或者可以将photo_thumb以某种方式动态添加到相应的类中?我尝试过经典和寄生继承,但我可能做得不对......我是Django的新手,也是python的新手。任何帮助表示赞赏。
答案 0 :(得分:3)
我同意@Gintautas。一般的经验法则是,如果需要重用模型字段和元选项,则创建一个抽象模型类;如果您只需要重用其他属性和方法,请使用一个简单的类。
在你的情况下,我会选择抽象类(因为photo
模型字段):
class PhotoModels(models.Model):
photo = models.ImageField(upload_to=u'something')
def photo_thumb(self):
if self.photo:
return u'<img src="%s" />' % (settings.MEDIA_URL +
'/thumbs/?h=64&w=80&c=50x0&p=' + self.photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
class meta:
abstract = True
class Something(PhotoModels):
title = models.CharField(max_length=200, default=u'')
text = models.CharField(max_length=250, default=u'', blank=True)
class SomethingElse(PhotoModels):
name = models.CharField(max_length=200, default=u'')
foo = models.CharField(max_length=250, default=u'', blank=True)
photo.upload_to = u'something_else'
def __unicode__(self):
return self.title;
......虽然这也是合法的:
class PhotoModels:
def photo_thumb(self):
if self.photo:
return u'<img src="%s" />' % (settings.MEDIA_URL +
'/thumbs/?h=64&w=80&c=50x0&p=' + self.photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
class Something(models.Model, PhotoModels):
title = models.CharField(max_length=200, default=u'')
text = models.CharField(max_length=250, default=u'', blank=True)
photo = models.ImageField(upload_to=u'something')
class SomethingElse(models.Model, PhotoModels):
name = models.CharField(max_length=200, default=u'')
foo = models.CharField(max_length=250, default=u'', blank=True)
photo = models.ImageField(upload_to=u'something_else')
def __unicode__(self):
return self.title;
答案 1 :(得分:1)
当然可以重复使用代码。只需将其分解为基类,并使您的类继承自该基类。这应该工作得很好。只是不要忘记基类要么继承自models.Model本身(然后我会建议making it abstract),要么你可以将可重用的代码放在mixin中;这意味着你的两个类都将继承自两个models.Model 和新的mixin基类。
答案 2 :(得分:1)
另一种解决方案可能是创建ImageField
的子类并覆盖contribute_to_class
方法:
class ImageWithThumbnailField(ImageField):
def contribute_to_class(self, cls, name):
super(ImageWithThumbnailField, self).contribute_to_class(cls, name)
def photo_thumb(self):
photo = getattr(self, name, None)
if photo:
return u'<img src="%s" />' % (settings.MEDIA_URL + '/thumbs/?h=64&w=80&c=50x0&p=' + photo.name)
else:
return u'(no photo)'
photo_thumb.short_description = u'Photo'
photo_thumb.allow_tags = True
photo_thumb.admin_order_field = 'photo'
setattr(cls, 'photo_thumb', photo_thumb);
我认为这更好,因为在调用photo_thumb
方法时,您期望存在self.photo
,如果您使用的是另一个使用抽象模型的解决方案,则无法保证。
编辑:请注意,您可以使用getattr(self, name)
动态访问该字段。所以,是的,保证我们有一些照片字段。
答案 3 :(得分:0)
也许我太早问了......我认为抽象基类可能就是答案。
http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes
我会检查并确认。