我在尝试实现(并真正映射)一个基于父模型的新模型对象时遇到了麻烦。
下面的Bucket
模型有一个基于两个category_options
的category
字段。
class Bucket(models.Model):
category_options = (
('personal', 'Personal'),
('social', 'Social'),
)
class BucketObjects(models.Manager):
def get_queryset(self):
return super().get_queryset()
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='buckets')
admin_user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='admin_user')
guest_user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='guest_user', blank=True)
category = models.CharField(max_length=30, choices=category_options)
...
objects = models.Manager()
bucketobjects = BucketObjects()
class Meta:
ordering = ('-created',)
def save(self, *args, **kwargs):
if self.stock_list:
self.stock_count = len(self.stock_list)
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)
我想在一个完全不同的模型SocialBucket
中创建一个新对象,当Bucket
模型实例被选择为基于上面category
字段的social
类别时:
class SocialBucket(models.Model):
bucket = models.ForeignKey(Bucket.objects.id, on_delete=models.CASCADE, related_name='social_buckets)
我如何去填充我的SocialBucket
模型与基于它的父,Bucket
,模型的新对象?
编辑:根据要求,这是我将使用的视图:
view.py
class CreateBucket(generics.CreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = BucketCreateSerializer
queryset = Bucket.objects.all()
serializer.py
class BucketCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Bucket
fields = ('owner','category','name','about')
read_only_fields = ['owner']
def create(self, validated_data):
user = self.context['request'].user
bucket = Bucket.objects.create(
owner=user,
**validated_data
)
bucket.save()
return bucket
尝试更改模型。Model, to Bucket:
class SocialBucket(Bucket)
bucket = models.ForeignKey(Bucket.objects.id, on_delete=models.CASCADE, related_name='social_buckets)
我认为最好的方法是使用post_save
信号,例如:
from django.db.models.signals import post_save
from django.dispatch import receiver
class Bucket(models.Model):
....
class SocialBucket(models.Model):
bucket = models.ForeignKey(Bucket, on_delete=models.CASCADE, related_name='social_buckets')
@receiver(post_save, sender=Bucket)
def create_social_bucket(sender, instance, created, **kwargs):
if created and instance.category == 'social':
SocialBucket.objects.create(bucket=instance)
也有一个替代方法来实现它。它将覆盖Bucket模型中的save方法:
class SocialBucket(models.Model):
bucket = models.ForeignKey('Bucket', on_delete=models.CASCADE, related_name='social_buckets') # putting the class of model as a string value to avoid import error
class Bucket(models.Model):
....
def create_social_bucket(self, create_social_bucket=False):
if create_social_bucket:
Social.objects.create(bucket_id=self.id)
def save(self, *args, **kwargs):
if self.stock_list:
self.stock_count = len(self.stock_list)
create_social_bucket = False
if self.pk is None and self.category == 'social':
create_social_bucket = True
super().save(*args, **kwargs)
self.create_social_bucket(create_social_bucket)
虽然不建议这样做。你可以破解和硬编码:
class BucketCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Bucket
fields = ('owner','category','name','about')
read_only_fields = ['owner']
def create(self, validated_data):
user = self.context['request'].user
bucket = Bucket.objects.create(
owner=user,
**validated_data
)
bucket.save()
# creating SocialBucket if category is social. You can later update it.
if bucket.category == 'social':
social_bucket = SocialBucket()
social_bucket.bucket = bucket
social_bucket.save()
return bucket