Копирование только атрибутов, не относящихся к отношениям django/python
Я копирую объект модели в другой, но хочу, чтобы при этом не копировались отношения
Например, предположим, что у вас есть такая модель:
class Dish(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=500)
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)
def __str__(self):
return self.name
Тогда я делаю:
my_dish = Dish.objects.get(pk=dish.id)
serializer = Dish_Serializer(my_dish)
my_new_object = serializer.data
Я хочу, чтобы my_new_object
включал только те атрибуты, которые не являются отношениями, в данном случае, имя и описание.
Как это сделать без прямого доступа к имени и описанию?
Предполагаю, что в вашем сериализаторе вы не хотите явно определять, какое поле сериализовать. В противном случае вы могли бы сделать следующее:
class Dish_Serializer(serializers.ModelSerializer):
class Meta:
model = Dish
fields = ['id','name', 'description']
Вероятно, вы можете определить эти поля динамически:
fields = [f.name for f in Dish._meta.concrete_fields]
или
fields = [f.name for f in Dish._meta.fields if not isinstance(f,ForeignKey)]
В конечном итоге, вы хотите получить my_new_object в формате словаря, а по условию pk даст вам только один объект dish. Поэтому вместо этого вы можете сделать следующее :
my_new_object = Dish.objects.filter(pk=dish.id).values("name", "description")[0]
Это даст вам именно то, что вы хотите, просто объявите нужные вам поля в значениях как атрибут fields.
Вы можете удалить поле из вашего сериализатора, используя .fields.pop(field_name)
метод, как в примере ниже Согласно тому, что я взял из Dynamically modifying fields
[drf-docs]:
class DynamicFieldsModelSerializer(serializers.ModelSerializer): """ A ModelSerializer that takes an additional `fields` argument that controls which fields should be displayed. """ def __init__(self, *args, **kwargs): # Don't pass the 'fields' arg up to the superclass fields = kwargs.pop('fields', None) # Instantiate the superclass normally super().__init__(*args, **kwargs) if fields is not None: # Drop any fields that are not specified in the `fields` >argument. allowed = set(fields) existing = set(self.fields) for field_name in existing - allowed: self.fields.pop(field_name)
Также вы можете сделать это в вашем view, как показано ниже в фрагменте кода:
my_dish = Dish.objects.get(pk=dish.id)
serializer = Dish_Serializer(my_dish)
desired_fields = {'id', 'name', 'description'}
all_fields = set(serializer.fields)
for field in all_fields:
if field not in desired_fields:
serializer.fields.pop(field)
my_new_object = serializer.data