Populating a tastypie resource for a multi-table inheritance Django model
考虑到以下代码,我想知道如何用每个实际记录数据填充
江户十一〔一〕号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Record(models.Model): content_type = models.ForeignKey(ContentType, editable=False, null=True) user = models.ForeignKey(User, related_name='records') issued = models.DateTimeField(auto_now_add=True) date = models.DateField() def save(self, *args, **kwargs): if not self.content_type: self.content_type = ContentType.objects.get_for_model(self.__class__) super(Record, self).save(*args, **kwargs) def as_leaf_class(self): model = self.content_type.model_class() if model == self.__class__: return self return model.objects.get(pk=self.id) class Record1(Record): # some fields # ... class RecordN(Record): # some fields |
埃多克斯1〔2〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | class BaseModelResource(ModelResource): class Meta(object): authentication = ApiKeyPlusWebAuthentication() authorization= Authorization() cache = SimpleCache() throttle = CacheDBThrottle( throttle_at=350, # 1 day expiration=86400 ) if settings.DEBUG: serializer = PrettyJSONSerializer() def obj_create(self, bundle, request=None, **kwargs): return super(BaseModelResource, self).obj_create(bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user) class BaseRecordResource(BaseModelResource): class Meta(BaseModelResource.Meta): filtering = { 'date': ALL } excludes = ['issued'] class RecordsResource(BaseRecordResource): class Meta(BaseRecordResource.Meta): resource_name = 'records' queryset = Record.objects.all() class Record1Resource(BaseRecordResource): class Meta(BaseRecordResource.Meta): resource_name = 'record1' queryset = Record1.objects.all() # ... class RecordNResource(BaseRecordResource): class Meta(BaseRecordResource.Meta): resource_name = 'recordn' queryset = RecordN.objects.all() |
号
好吧,我刚刚解决了。我简化了代码。
给出以下代码…
埃多克斯1〔9〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from django.db import models from model_utils.managers import InheritanceManager class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) # https://github.com/carljm/django-model-utils#inheritancemanager objects = InheritanceManager() class Restaurant(Place): custom_field = models.BooleanField() class Bar(Place): custom_field = models.BooleanField() |
埃多克斯1〔10〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from core.models import Place, Restaurant, Bar # http://django-tastypie.readthedocs.org/en/latest/cookbook.html#pretty-printed-json-serialization from core.utils import PrettyJSONSerializer from tastypie.resources import ModelResource class PlaceResource(ModelResource): class Meta: queryset = Place.objects.select_subclasses() resource_name = 'place' serializer = PrettyJSONSerializer() class RestaurantResource(ModelResource): class Meta: queryset = Restaurant.objects.all() resource_name = 'restaurant' serializer = PrettyJSONSerializer() class BarResource(ModelResource): class Meta: queryset = Bar.objects.all() resource_name = 'bar' serializer = PrettyJSONSerializer() |
。
产量
江户十一〔11〕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "meta": { "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1 }, "objects": [ { "address":"dawdaw", "custom_field": true, "id":"1", "name":"dwdwad", "resource_uri":"/api/v1/bar/1/" } ] } |
好啊
埃多克斯1〔12〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "meta": { "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1 }, "objects": [ { "address":"nhnhnh", "custom_field": true, "id":"2", "name":"nhnhnh", "resource_uri":"/api/v1/restaurant/2/" } ] } |
。
好啊
埃多克斯1〔13〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { "meta": { "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 2 }, "objects": [ { "address":"dawdaw", "id":"1", "name":"dwdwad", "resource_uri":"/api/v1/place/1/" }, { "address":"nhnhnh", "id":"2", "name":"nhnhnh", "resource_uri":"/api/v1/place/2/" } ] } |
。
我想达到的目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "meta": { "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 2 }, "objects": [ { "address":"dawdaw", "custom_field": true, "id":"1", "name":"dwdwad", "resource_uri":"/api/v1/bar/1/" }, { "address":"nhnhnh", "custom_field": true, "id":"2", "name":"nhnhnh", "resource_uri":"/api/v1/restaurant/2/" } ] } |
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | from core.models import Place, Restaurant, Bar # http://django-tastypie.readthedocs.org/en/latest/cookbook.html#pretty-printed-json-serialization from core.utils import PrettyJSONSerializer from tastypie.resources import ModelResource class RestaurantResource(ModelResource): class Meta: queryset = Restaurant.objects.all() resource_name = 'restaurant' serializer = PrettyJSONSerializer() class BarResource(ModelResource): class Meta: queryset = Bar.objects.all() resource_name = 'bar' serializer = PrettyJSONSerializer() class PlaceResource(ModelResource): class Meta: queryset = Place.objects.select_subclasses() resource_name = 'place' serializer = PrettyJSONSerializer() def dehydrate(self, bundle): # bundle.data['custom_field'] ="Whatever you want" if isinstance(bundle.obj, Restaurant): restaurant_res = RestaurantResource() rr_bundle = restaurant_res.build_bundle(obj=bundle.obj, request=bundle.request) bundle.data = restaurant_res.full_dehydrate(rr_bundle).data elif isinstance(bundle.obj, Bar): bar_res = BarResource() br_bundle = bar_res.build_bundle(obj=bundle.obj, request=bundle.request) bundle.data = bar_res.full_dehydrate(br_bundle).data return bundle |
。
在recordsresource类中,还需要添加model字段(请参见https://github.com/tomcristie/django rest framework/blob/master/djangorestframework/resources.py l232-234)
1 2 3 4 5 6 | class RecordsResource(BaseRecordResource): model = Record class Meta(BaseRecordResource.Meta): resource_name = 'records' queryset = Record.objects.all() |
从一开始就解释:
Django有三种继承方式。
通常,您只需要使用父类来保存您不想为每个孩子输入的信息模型。这个类不会单独使用,所以抽象基类就是你想要的。
如果您正在对现有模型进行子类化(可能是完全是另一个应用程序),并希望每个模型都有自己的数据库表,多表继承是前进的道路。
最后,如果只想修改模型,在不以任何方式更改模型字段的情况下,可以使用代理模型。
这里的选择是多表继承
多表继承Django支持的第二种类型的模型继承是,当层次结构中的每个模型都是一个单独的模型时。每个模型都对应于自己的数据库表,可以单独查询和创建。继承关系引入子模型与其每个父模型之间的链接(通过自动创建的OneTooneField)引用
从
1 2 3 4 | if hasattr(a_example_record, 'record1'): # ... elif hasattr(a_example_record, 'record2'): # ... |
号
因此,既然我们知道了如何从父母那里得到孩子,并且我们需要向