I have 2 serializers serializer_1 and serializer_2 which are both model serilizer i want to execute update method of serializer_1 from create method of serializer_2 how can i achieve that?
class serializer_1(serializers.ModelSerializer):
date = serializers.DateTimeField(required=False, allow_null=True)
ispublic = serializers.BooleanField(allow_null=False)
details_api_url = serializers.SerializerMethodField()
dispute_types = OtherSerializer(many=True, required=False, write_only=True)
nature_of_dispute_list = serializers.SerializerMethodField()
plaintiff = OtherSerializer(many=True, required=False, write_only=True)
defendant = OtherSerializer(many=True, required=False, write_only=True)
claims_rep = OtherSerializer(many=True, required=False, write_only=True)
class Meta:
model = Media
fields = "__all_"
def update(self, instance, validated_data):
date = validated_data.pop('close_out_date', None)
plaintiff_data = validated_data.pop('plaintiff', [])
defendant_data = validated_data.pop('defendant', [])
claims_rep_data = validated_data.pop('claims', [])
is_summary_public_previous = instance.is_summary_public
obj = super().update(instance, validated_data)
return obj
class serializer_2(serializers.ModelsSerializer):
class Meta:
model = Fedia
fields = "__all__"
def create(self, validated_data):
request = self.context['request']
**serilizer_1_data** = validated_data.pop('serialzer_1_data', None)
is_final = validated_data.get('is_final')
serializer_1_object = Media.objects.create(**serializer_1_data)
if is_final:
**Call Serializer_1 Update method**
I have access to date,plaintiff etc mentioned under serializer_1 in create method of serilizer_2 through serilizer_1_data
Related
models.py
class Rooms(models.Model):
objects = None
room_num = models.IntegerField(verbose_name='Комната')
room_bool = models.BooleanField(default=True,verbose_name='Релевантность')
category = models.CharField(max_length=150,verbose_name='Категория')
price = models.CharField(max_length=105,verbose_name='Цена (сум)')
def __str__(self):
return f'{self.room_num}'
class Meta:
verbose_name = 'Комнату'
verbose_name_plural = 'Комнаты'
class Registration(models.Model):
objects = None
rooms = models.ForeignKey(Rooms, on_delete=models.CASCADE,verbose_name='Номер',help_text='Номер в который хотите заселить гостя!')
first_name = models.CharField(max_length=150,verbose_name='Имя')
last_name = models.CharField(max_length=150,verbose_name='Фамилия')
admin = models.ForeignKey(User, on_delete=models.CASCADE,verbose_name='Администратор')
pasport_serial_num = models.CharField(max_length=100,verbose_name='Серия паспорта',help_text='*AB-0123456')
birth_date = models.DateField(verbose_name='Дата рождения')
img = models.FileField(verbose_name='Фото документа',help_text='Загружайте файл в формате .pdf')
visit_date = models.DateTimeField(
default=datetime.datetime(year=year, month=month, day=day, hour=datetime.datetime.now().hour,
minute=datetime.datetime.now().minute, second=00,),verbose_name='Дата прибытия')
leave_date = models.DateTimeField(
default=datetime.datetime(year=year, month=month, day=day + 1, hour=12, minute=00, second=00),verbose_name='Дата отбытия')
guest_count = models.IntegerField(default=1,verbose_name='Кол-во людей')
room_bool = models.BooleanField(default=False,verbose_name='Релевантность',help_text='При бронирование отключите галочку')
price = models.CharField(max_length=105,default='Появится после сохранения!',verbose_name='Цена (сум)')
def __str__(self):
return f'{self.rooms},{self.last_name},{self.first_name},{self.room_bool}'
class Meta:
verbose_name = 'Номер'
verbose_name_plural = 'Регистрация'
signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Registration
#receiver(post_save, sender=Registration)
def create_profile(sender, instance, created, **kwargs):
if created:
instance.rooms.room_bool = False
instance.rooms.save()
this is the code in the signals that updates the value from another model according to the value of another WHEN I CREATE (if in model 1 it will be False, then in model 2 it will also be False) how can I make it so that when EDITING changes the values
I recommend use pre_save signal for this situation
#receiver(pre_save, sender=Registration)
def create_profile(instance, *args, **kwargs):
if instance.pk #Its update
else: #Its create
django.db.models.signals.pre_save
This is sent at the beginning of a model’s save() method.
django.db.models.signals.post_save
Like pre_save but sent at the end of the save() method
your model will not has id when creating so you can catch with pk instance is data for your model
#receiver(post_save, sender=Registration)
def create_profile(sender, instance, created,**kwargs):
if created:
instance.rooms.room_bool = instance.room_bool
instance.rooms.save()
instance.price = instance.rooms.price
instance.save()
elif not created:
instance.rooms.room_bool = instance.room_bool
instance.rooms.save()
I'm coding some backend software for a second-hand selling app using Django and DjangoRestFramework. Right now, I'm trying to send a Response object that contains a list of products, but I seem not to be able to return an actual list of products, as I'm getting an error saying
ListSerializer is not JSON serializable.
I've tried both using the serializer constructor like this:
ProductoSerializer(products, many=True)
And by creating a list of ProductoSerializer.data and then creating the Response object with that.
Here's the serializers that I'm using:
class UserSerializer(serializers.HyperlinkedModelSerializer):
ciudad = serializers.SerializerMethodField()
conectado = serializers.SerializerMethodField()
class Meta:
model = Usuario
fields = ('uid', 'nombre', 'ciudad', 'conectado')
def get_ciudad(self, obj):
geolocator = Nominatim(user_agent="bookalo")
location = geolocator.reverse(str(obj.latitud_registro) + ',' + str(obj.longitud_registro))
return location.raw['address']['city']
def get_conectado(self, obj):
ahora = timezone.now()
result = relativedelta(ahora, obj.ultima_conexion)
return result.days == 0 and result.hours == 0 and result.months == 0 and result.years == 0 and result.minutes < 5
class TagSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Tag
fields = ('nombre')
class MultimediaSerializer(serializers.HyperlinkedModelSerializer):
contenido_url = serializers.SerializerMethodField()
class Meta:
model = ContenidoMultimedia
fields = ('contenido_url', 'orden_en_producto')
def get_contenido_url(self, obj):
return obj.contenido.url
class MiniProductoSerializer(serializers.HyperlinkedModelSerializer):
contenido_multimedia = serializers.SerializerMethodField()
class Meta:
model = Producto
fields = ('nombre', 'precio', 'estado_venta', 'contenido_multimedia')
def get_contenido_multimedia(self, obj):
contenido = ContenidoMultimedia.objects.get(producto=obj.pk, orden_en_producto=0)
return MultimediaSerializer(contenido)
class ProductoSerializer(serializers.HyperlinkedModelSerializer):
vendido_por = UserSerializer(read_only=True)
tiene_tags = TagSerializer(many=True, read_only=True)
contenido_multimedia = serializers.SerializerMethodField()
valoracion_media_usuario = serializers.SerializerMethodField()
class Meta:
model = Producto
fields = ('nombre', 'precio', 'estado_producto', 'estado_venta', 'latitud', 'longitud', 'tipo_envio', 'descripcion', 'vendido_por', 'tiene_tags', 'num_likes', 'contenido_multimedia')
def get_contenido_multimedia(self, obj):
contenido = ContenidoMultimedia.objects.filter(producto=obj.pk).order_by('orden_en_producto')
return MultimediaSerializer(contenido, many=True)
def get_valoracion_media_usuario(self, obj):
return Usuario.objects.get(pk=obj.vendido_por).media_valoraciones
class ValidacionEstrellaSerializer(serializers.HyperlinkedModelSerializer):
usuario_que_valora = UserSerializer(read_only=True)
producto_asociado = serializers.SerializerMethodField()
class Meta:
model = ValidacionEstrella
fields = ('estrellas', 'comentario', 'timestamp', 'usuario_que_valora', 'producto_asociado')
def get_producto_asociado(self, obj):
producto = Producto.objects.get(pk=obj.producto)
return MiniProductoSerializer(producto)
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
usuario_valorado_estrella = serializers.SerializerMethodField()
productos_favoritos = serializers.SerializerMethodField()
class Meta:
model = Usuario
fields = ('uid', 'nombre', 'esta_baneado', 'usuario_valorado_estrella', 'producto_del_usuario')
def get_usuario_valorado_estrella(self, obj):
validaciones = ValidacionEstrella.objects.filter(usuario_valorado=obj.pk).order_by('-timestamp')
return ValidacionEstrellaSerializer(validaciones, many=True, read_only=True)
def get_productos_favoritos(self, obj):
favoritos = Producto.objects.filter(le_gusta_a__in=[obj.pk])
return ProductoSerializer(favoritos, many=True, read_only=True)
class ReportSerializer(serializers.HyperlinkedModelSerializer):
#usuario_reportado = serializers.SerializerMethodField()
usuario_reportado = UserSerializer(read_only=True)
class Meta:
model = Report
fields = ('usuario_reportado', 'causa')
And here's the views.py function that I'm trying to code:
#api_view(['POST'])
#permission_classes((permissions.AllowAny,))
def SearchProduct(request, format=None):
if request.method != 'POST':
return Response(status=status.HTTP_400_BAD_REQUEST)
preposiciones = ['a','ante','bajo','cabe','con','contra','de','desde','en','entre',
'hacia','hasta','para','por','segun','sin','so','sobre','tras']
try:
search = request.POST.get('busqueda')
except:
return Response(status=status.HTTP_404_NOT_FOUND)
products = Producto.objects.none()
for word in search.split():
if word not in preposiciones:
productos_palabra = Producto.objects.filter(nombre__contains=word)
products = products | productos_palabra
products.distinct()
product_list = []
for prod in products:
product_list.append(ProductoSerializer(prod).data)
return Response({'productos': product_list}, status=status.HTTP_200_OK)
I'm using a request object because I also have to server a WebPage, and not only a mobile app, with the same function (the webpage part is still not coded though).
It should return all the products that contain at least one of the words from the user's search, and it all should be structured based on the ProductoSerializer object, but for some reason, it's outputting that error and I'm not quite sure how to fix it.
Thanks in advance, and if you need any extra information which I've missed, please do ask for it... It's been a long day and I probably missed something.
Seems like when you use SerializerMethodField you return serializer instance but not it's data:
For instance:
contenido_multimedia = serializers.SerializerMethodField()
def get_contenido_multimedia(self, obj):
contenido = ContenidoMultimedia.objects.filter(producto=obj.pk).order_by('orden_en_producto')
return MultimediaSerializer(contenido, many=True).data # <-- here try to add .data
It should be changed for all SerializerMethodField methods.
I have a model which contains a foreign key. When I my models all fields are updated except the foreign key.
My models:
class Produit (models.Model):
titre=models.CharField(max_length=100)
description=models.TextField()
photo_principal=models.ImageField(upload_to='produits/',default='image.jpg')
photo_1 = models.ImageField(upload_to='produits/', default='image.jpg')
photo_2 = models.ImageField(upload_to='produits/', default='image.jpg')
photo_3 = models.ImageField(upload_to='produits/', default='image.jpg')
prix=models.FloatField()
new_prix=models.FloatField()
categorie=models.ForeignKey(Categorie,related_name= 'produit', on_delete=models.CASCADE)
serializers.py
class ProduitUpdateSerializer(serializers.ModelSerializer):
categorie_id = serializers.PrimaryKeyRelatedField(queryset=Categorie.objects.all(),source='categorie.id')
class Meta:
model = Produit
fields = ['titre', 'description', 'photo_principal', 'photo_1', 'photo_2', 'photo_3', 'prix', 'new_prix',
'categorie_id', ]
def update(self, instance, validated_data):
print(validated_data)
instance.categorie_id = validated_data.get('categorie_id',instance.categorie_id)
instance.titre = validated_data.get('titre', instance.titre)
instance.description = validated_data.get('description', instance.description)
instance.photo_principal = validated_data.get('photo_principal', instance.photo_principal)
instance.photo_1 = validated_data.get('photo_1', instance.photo_1)
instance.photo_2 = validated_data.get('photo_2', instance.photo_2)
instance.photo_3 = validated_data.get('photo_3', instance.photo_3)
instance.prix = validated_data.get('prix', instance.prix)
instance.new_prix = validated_data.get('new_prix', instance.new_prix)
instance.save()
return instance
why not call super like so as the modelserialiser has additional iteration for m2m db.
def update(self, instance, validated_data):
# MANIPULATE DATA HERE BEFORE INSERTION
instance = super(ProduitUpdateSerializer,self).update(instance, validated_data)
# ADD CODE HERE THAT YOU WANT TO VIEW
return instance
You shouldn't play with the id directly in that case since the serializer will return an object:
class ProduitUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Produit
fields = ['titre', 'description', 'photo_principal', 'photo_1', 'photo_2', 'photo_3', 'prix', 'new_prix',
'categorie', ]
def update(self, instance, validated_data):
print(validated_data)
instance.categorie = validated_data.get('categorie', instance.categorie)
instance.titre = validated_data.get('titre', instance.titre)
instance.description = validated_data.get('description', instance.description)
instance.photo_principal = validated_data.get('photo_principal', instance.photo_principal)
instance.photo_1 = validated_data.get('photo_1', instance.photo_1)
instance.photo_2 = validated_data.get('photo_2', instance.photo_2)
instance.photo_3 = validated_data.get('photo_3', instance.photo_3)
instance.prix = validated_data.get('prix', instance.prix)
instance.new_prix = validated_data.get('new_prix', instance.new_prix)
instance.save()
return instance
This is more DRY Code. May exclude fields from the list to avoid updating
def update(self, instance, validated_data):
fields=instance._meta.fields
exclude=[]
for field in fields:
field=field.name.split('.')[-1] #to get coulmn name
if field in exclude:
continue
exec("instance.%s = validated_data.get(field, instance.%s)"%(field,field))
instance.save()
return instance
I'm trying to map a foreign key to POST data when creating a new object through a serializer. There are two foreign keys in the object, one is serializing perfectly, the other is creating an error.
Model:
class Event(models.Model):
owner = models.ForeignKey('auth.User', related_name='owner', blank=True)
date = models.DateField('eventdate')
time = models.TimeField('eventtime', default=now)
eventtype = models.ForeignKey(EventType, related_name='eventtype', blank=True)
# duration = models.DurationField()
location = models.CharField(max_length=200, blank=True)
attenders = models.ManyToManyField(User, related_name='attenders')
invited = models.ManyToManyField(User, related_name='invitedlist')
View:
class EventMixin(RetrieveUpdateDestroyAPIView, CreateAPIView):
serializer_class = EventSerializer
def get_queryset(self):
return Event.objects.all()
def partial_update(self, request, *args, **kwargs):
request['owner'] = request.user
sname = request['eventtype']
request['eventtype'] = EventType.objects.filter(sname=sname)
json_str = json.dumps(self.request.data)
data = json.loads(json_str)
try:
invited = list(data['toInvite'])
for i in invited:
for j in User.objects.filter(username=i):
invite = EventInvite(invited=j, sender=request.user, event=self.get_object())
invite.save()
self.get_object().invited.add()
except KeyError:
pass
return super(EventMixin, self).partial_update(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
new = {}
new['owner'] = request.user.__dict__
new['date'] = request.data['date']
new['time'] = request.data['time']
new['location'] = request.data['location']
sname = request.data['eventtype']
new['eventtype'] = EventType.objects.get(sname=sname).__dict__
json_str = json.dumps(self.request.data)
data = json.loads(json_str)
serializer = EventMixinSerializer(data=new)
with open('/tmp/log.txt', 'w+') as f:
f.write(str(serializer.is_valid()))
f.write(str(serializer.validated_data))
f.close()
serializer.is_valid();
serializer.save()
try:
invited = list(data['toInvite'])
for i in invited:
for j in User.objects.filter(username=i):
invite = EventInvite(invited=j, sender=request.user, event=self.get_object())
invite.save()
self.get_object().invited.add()
except KeyError:
pass
Serializer:
class EventMixinSerializer(serializers.ModelSerializer):
owner = UserSerializer(read_only=True)
eventtype = EventTypeSerializer()
attenders = FriendsListingField(read_only=True)
invited = FriendsListingField(read_only=True)
class Meta:
model = Event
fields = ('owner', 'eventtype', 'date', 'time', 'location', 'id', 'attenders', 'invited')
def create(self, validated_data):
owner = validated_data.pop('owner')
owner = owner.instance
eventtype = validated_data.pop('eventtype')
eventtype = eventtype.instance
event = Event.objects.create(owner=owner, eventtype=eventtype, **validated_data)
event.save()
return event
Error when owner field present:
False
{'owner': OrderedDict([('username', ['A user with that username already exists.'])])}
Result when UserSerializer(read_only=True) (pretty much diabling it):
True
OrderedDict([('eventtype', OrderedDict([('lname', 'Swimming'), ('sname', 'SWM'), ('category', '1')])), ('date', datetime.date(2015, 12, 22)), ('$
(Notice the event type data in the result)
Thanks!
You need to remove the validators from UserSerializer.
Assuming UserSerializer is a User ModelSerializer it'll extract the unique constraint on the User.username from the Model and your validation will fail.
To work this around you'll need to remove the UniqueValidator by overriding the validators list for the username field of the UserSerializer
I have any models and the view to generate a form wizard, once the user submit the last form, I want the app send a confirmation email, the current user's mail is in the native Django model, how I can access to his email? and how I can access to "curso" name too? thanks for your help.
models.py
class Datos_Basicos (models.Model):
user = models.OneToOneField(User)
tipo_identificacion = models.CharField(max_length=25)
identificacion = models.CharField(max_length=20,primary_key='True')
telefono = models.CharField(max_length=10)
celular = models.CharField(max_length=11)
class Curso(models.Model):
curso = models.CharField(max_length=15)
fk_programa = models.ForeignKey(Programa, verbose_name="programa")
class Inscripcion(models.Model):
fecha = models.DateField(default = datetime.datetime.now)
fk_subsede = models.ForeignKey(Subsede, verbose_name="sede")
fk_curso = models.ForeignKey(Curso, verbose_name="curso")
class Inscrito(models.Model):
fk_datos_basicos = models.OneToOneField(Datos_Basicos, verbose_name="datos basicos")
fk_inscripcion = models.OneToOneField(Inscripcion, verbose_name="curso", null=False)
forms.py
class Datos_basicos_form(forms.ModelForm):
tipo_identificacion = forms.ChoiceField(choices=IDENTIFICACION_CHOICES)
class Meta:
model = Datos_Basicos
fields = ['tipo_identificacion', 'identificacion', 'telefono', 'celular']
class Inscrito_form(forms.Form):
genero = forms.ChoiceField(choices=GENEROS_CHOICES)
fecha_nacimiento = forms.DateField(widget=extras.SelectDateWidget(years=ANIOS_CHOICES))
grupo_etnico = forms.ChoiceField(choices=GRUPO_ETNICO_CHOICES)
condicion = forms.ModelChoiceField(queryset=Condicion.objects.all())
condicion_medica = forms.CharField(max_length=200)
eps = forms.CharField(max_length=100)
espacio_geografico = forms.ChoiceField(choices=ESPACIO_GEOGRAFICO_CHOICES)
barrio = forms.ModelChoiceField(queryset=Barrio.objects.order_by('barrio'))
direccion = forms.CharField(max_length=50)
jornada_estudio = forms.ChoiceField(choices=JORNADA_ESTUDIO_CHOICES)
class Inscripcion_form(forms.ModelForm):
class Meta:
model = Inscripcion
exclude = ['fecha']
views.py
from formtools.wizard.views import SessionWizardView
class InscritoWizard(SessionWizardView):
template_name = "inscripcion.html"
def done(self, form_list, **kwargs):
forms_data = self.process_form_data(form_list)
forms_data[1]['user'] = self.request.user ### current user
forms_data[2]['edad'] = hoy.year - forms_data[2]['fecha_nacimiento'].year - ((hoy.month, hoy.day) < (forms_data[2]['fecha_nacimiento'].month, forms_data[2]['fecha_nacimiento'].day))
inscripcion = Inscripcion.objects.create(**forms_data[0])
datos_basicos = Datos_Basicos.objects.create(**forms_data[1])
forms_data[2]['fk_datos_basicos'] = datos_basicos
forms_data[2]['fk_inscripcion'] = inscripcion
Inscrito.objects.create(**forms_data[2])
--->send_mail('Subject here', 'Here is the message.','from#example.com',['to#example.com'], fail_silently=False)
return render_to_response('gracias.html', {'forms_data': forms_data})
def process_form_data(self, form_list):
data = [form.cleaned_data for form in form_list]
return data
In the form wizard methods, you can access the logged in user with self.request.user, therefore you can get their email with self.request.user.email.