Null in response which should't exist Django - python

When I send request in Postman like this:
it returns me all fields fine expect the profile_photo. profile_photo in response is null and I don't know what is the problem. It should be the new uuid photo name.
Here is my model:
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
city = models.CharField(max_length=150, blank=True)
description = models.CharField(max_length=1000, blank=True)
profile_photo = models.CharField(max_length=500, blank=True)
date_joined = models.DateTimeField(default=timezone.now)
about = models.TextField(_(
'about'), max_length=500, blank=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = CustomAccountManager()
object = models.Manager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'city']
def __str__(self):
return self.email
This is my view:
class CustomUserUpdate(generics.UpdateAPIView):
permission_classes = [IsAuthenticated]
queryset = User.objects.all()
serializer_class = UserUpdateSerializer
def get_object(self):
return self.request.user
This is my serializer. Here i am setting the new photo name. When I print the new name here like this: print(instance.profile_photo) it shows me the new file name fine. But in the response i get null.
class UserUpdateSerializer(serializers.ModelSerializer):
profile_photo = serializers.FileField(required=False)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'city', 'description', 'profile_photo')
def __init__(self, *args, **kwargs):
super(UserUpdateSerializer, self).__init__(*args, **kwargs)
self.fields['email'].required = False
self.fields['description'].required = False
def update(self, instance, validated_data):
if instance.id == self.context['request'].user.id:
instance.email = validated_data.get('email', instance.email)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.city = validated_data.get('city', instance.city)
instance.description = validated_data.get('description', instance.description)
uploaded_file = validated_data.get('profile_photo', None)
if uploaded_file:
validate_extension(uploaded_file.name)
instance.profile_photo = handle_uploaded_file(uploaded_file)
instance.save()
return instance
def handle_uploaded_file(file):
extension = os.path.splitext(file.name)[1]
new_filename = f"{uuid.uuid4()}{extension}"
destination = open(f'static/user/images/{new_filename}', 'wb+')
for chunk in file.chunks():
destination.write(chunk)
destination.close()
return new_filename
def validate_extension(filename):
extension = os.path.splitext(filename)[1].replace(".", "")
if extension.lower() not in ALLOWED_IMAGE_EXTENSIONS:
raise serializers.ValidationError(
(f'Invalid uploaded file type: {filename}'),
code='invalid',
)

While sending requests you are passing file as input to the serializer. Serializer validates it and saves it. Till here it is perfectly fine.
Now while returning the response it expects a file from instance.profile_photo but to the serializer validator's surprise, it contains a string value (i.e UUID file name). The problem is here!
We got the bug point. Let's solve it.
To solve it, differentiate the names for the request(File) and response (File name i.e UUID string):
class UserUpdateSerializer(serializers.ModelSerializer):
profile_image = serializers.FileField(required=False, write_only=True)
profile_photo = serializers.ReadOnlyField()
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'city', 'description', 'profile_photo', 'profile_image')
def __init__(self, *args, **kwargs):
super(UserUpdateSerializer, self).__init__(*args, **kwargs)
self.fields['email'].required = False
self.fields['description'].required = False
def update(self, instance, validated_data):
if instance.id == self.context['request'].user.id:
instance.email = validated_data.get('email', instance.email)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.city = validated_data.get('city', instance.city)
instance.description = validated_data.get('description', instance.description)
uploaded_file = validated_data.get('profile_image', None)
if uploaded_file:
validate_extension(uploaded_file.name)
instance.profile_photo = handle_uploaded_file(uploaded_file)
instance.save()
return instance
We have solved the bug!

Related

(django) 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte

I am now trying to assign two foreignkey onto the same custom user model, the username & profile image field.
Custom User model:
class Account(AbstractBaseUser, PermissionsMixin):
class Meta:
verbose_name_plural = "Account List"
email = models.EmailField(max_length=255, unique=True)
username = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, default="")
profile_image = models.ImageField(max_length=255, upload_to=profile_image_path, blank=True, unique=True)
about = models.TextField(max_length=255, default='Write something about yourself...', blank=True)
start_date = models.DateTimeField(default=timezone.now)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "name"]
def __str__(self):
return self.username
Thread model:
class Thread(models.Model):
options = (('active', 'Active'), ('deactivated', 'Deactivated'))
username = models.ForeignKey(Account, on_delete=models.CASCADE, to_field='username', related_name='user')
profile_image = models.ForeignKey(Account, on_delete=models.CASCADE, to_field='profile_image', related_name='profile')
alt = models.TextField(max_length=255, blank=True)
image = models.ImageField(max_length=255, upload_to=thread_image_path, default='images/family.png')
content = models.TextField(blank=True)
created = models.DateTimeField(default=timezone.now)
status = models.CharField(max_length=11, choices=options, default='active')
However, whenever I try to create a Thread, I always encounter the error:
UnicodeDecodeError at /api/public/thread/
'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
Request Method: GET
Request URL: http://127.0.0.1:8000/api/public/thread/
Django Version: 4.0.4
Exception Type: UnicodeDecodeError
Exception Value:
'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
Exception Location: c:\Users\85291\Desktop\vscode\my-app\web\env\lib\site-packages\rest_framework\utils\encoders.py, line 50, in default
This error occurred right after I assign the foreignkey to the profile image, the serializer is unable to serialize the image to the API endpoint. I have tried going to encoders.py and change the encoder to utf16, but the problem remained.
Anyone has an idea what's wrong with my code?
Edit:
Custom User serializer.py:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = (
'id',
'email',
'username',
'name',
'profile_image',
'about',
'start_date',
'is_active',
'last_login'
)
read_only_field = ('start_date',)
class RegisterSerializer(UserSerializer):
password = serializers.CharField(max_length=128, min_length=8, required=True, write_only=True)
email = serializers.EmailField(max_length=128, required=True, write_only=True)
username = serializers.CharField(max_length=128, required=True)
name = serializers.CharField(max_length=128, required=True)
class Meta:
model = Account
fields = [
'email',
'username',
'password',
'name',
]
extra_kwargs = {'password': {'wirte_only': True}}
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
class LoginSerialier(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
refresh = self.get_token(self.user)
data['user'] = UserSerializer(self.user).data
data['refresh'] = str(refresh)
data['access'] = str(refresh.access_token)
if api_settings.UPDATE_LAST_LOGIN:
update_last_login(None, self.user)
return data
Custom User serializer.py:
class RegisterViewSet(viewsets.ModelViewSet):
permission_classes = (AllowAny,)
def create(self, request, format='json'):
serializer = RegisterSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
json = serializer.data
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class LoginViewSet(viewsets.ModelViewSet, TokenObtainPairView):
serializer_class = LoginSerialier
permission_classes = (AllowAny,)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
return Response(serializer.validated_data, status=status.HTTP_200_OK)
class RefreshViewSet(viewsets.ViewSet, TokenRefreshView):
permission_classes = (AllowAny,)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
return Response(serializer.validated_data, status=status.HTTP_200_OK)
class UserViewSet(viewsets.ModelViewSet):
queryset = Account.objects.none()
serializer_class = UserSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
return Account.objects.filter(id=self.request.user.id)
class BlacklistTokenView(viewsets.ModelViewSet):
permission_classes = (AllowAny,)
def post(self, request):
try:
refresh_token = request.data["refresh_token"]
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response(status=status.HTTP_400_BAD_REQUEST)
Thread serializer.py:
class ThreadSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField(format="%d %B, %Y %H:%M:%S")
class Meta:
model = Thread
fields = (
'id',
'username',
'profile_image',
'alt',
'image',
'content',
'created',
'status')
Thread view.py
class ThreadView(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = ThreadSerializer
def get_queryset(self):
username = self.request.user.username
return Thread.objects.filter(username=username)
class ThreadViewSets(viewsets.ModelViewSet):
permission_classes = (AllowAny,)
serializer_class = ThreadSerializer
queryset = Thread.objects.all()
I think you can deal with the uploaded image.
class ThreadSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField(format="%d %B, %Y %H:%M:%S")
uploaded_image = serializers.FileField(
max_length = 1000000,
allow_empty_file = False,
write_only = True
)
profile_image = UserSerializer(read_only = True)
class Meta:
model = Thread
fields = (
...,
'uploaded_image',
)
extra_kwargs = {
'image': { 'read_only': True }
}
def create(self, validated_data):
image_data = validated_data.pop('uploaded_image')
thread_obj = Thread(**validated_data)
thread_obj.image = image_data
thread_obj.save()
return thread_obj
In frontend, you need to upload the image with the key uploaded_image.

Can't get Django REST to save POST object request in model

Trying to allow users to create an object and save it in my model. My front-end POST requests are getting a 201 confirmation response, so no traceback error from the backend. The data seems to be getting serialized but not saved in my model.
Here is my code...
model.py:
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)
name = models.CharField(max_length=35)
created = models.DateTimeField(default=timezone.now, blank=True)
slug = AutoSlugField(populate_from = "random_string", blank=True)
stock_count = models.IntegerField(blank=True, null=True)
stock_list = ArrayField(models.CharField(max_length=6,null=True),size=30,null=True, blank=True)
about = models.CharField(max_length=200)
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)
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
view.py:
class CreateBucket(generics.CreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = BucketCreateSerializer
queryset = Bucket.objects.all()
How can I go about solving this?

python django : Got AttributeError when attempting to get a value for field `username` on serializer `PerformerSerializer`

Hi fellow programmers,
I am getting the following error when I try to visit my url can you please point out the mistake in my code. Is there any error in my serializer or view. I will be gateful if you find that.
Got AttributeError when attempting to get a value for field username on serializer PerformerSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'user'.
models.py
class User(AbstractBaseUser):
username = models.CharField(_('Username'), unique=True,max_length=20)
email = models.EmailField(_('Email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
last_login = models.DateTimeField(auto_now=True)
date_joined = models.DateTimeField(auto_now_add=True)
full_name = models.CharField(_("Full Name"), max_length=50,null=True)
date_of_birth = models.DateField(_("Date of birth"), auto_now=False, auto_now_add=False,null=True)
is_verified = models.BooleanField(_("Verified"), default=False)
profileImage = models.ImageField(_('Profile Image'),null=True, upload_to=None, height_field=None, width_field=None, max_length=100)
gender = models.CharField(_("Gender"), max_length=6, choices=GENDER_CHOICES,null=True)
profileTitle = models.CharField(_('Title'), max_length=20,null=True)
profileBio = models.TextField(_('Bio'),null=True)
profileWebsite = models.URLField(_('Website'), max_length=25,null=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
def has_perm(self,perm,obj=None):
return self.is_admin
def has_module_perms(self,app_label):
return True
def __str__(self):
return self.username
def natural_key(self):
return (self.username)
class Song(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(_("Name"), max_length=50)
song = models.FileField(_("Song"), upload_to=None, max_length=100)
song_image = models.ImageField(upload_to=None, height_field=None, width_field=None, max_length=100)
likes = models.IntegerField(_("Likes"),default=0)
views = models.IntegerField(_("Views"),default=0)
performer = models.ManyToManyField('self',verbose_name=_("Performed By"),related_name='artist_in_song')
def performer_user(self, username):
performer = Song.objects.get(user__username=username)
if not self.is_performer(performer):
self.performer.add(performer)
self.save()
return True
return False
def is_performer(self, username):
return self.performer.all().filter(user__username=username).exists()
serializers.py
class PerformerSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
class Meta:
model = Song
fields = ('username',)
class UserSerializer(serializers.ModelSerializer):
#id = serializers.ReadOnlyField(source='user.id')
class Meta:
model = User
fields = ('id',)
class SongSerializer(serializers.ModelSerializer):
performer = PerformerSerializer(many=True, read_only= True)
user= UserSerializer(many=False, read_only= True)
class Meta:
model = Song
fields = ('user','performer','id','name','song','song_image','likes','views')
read_only_fields = ('likes','views')
views.py
class SongCreateView(generics.ListCreateAPIView):
queryset = Song.objects.all()
serializer_class = SongSerializer
permission_classes = [IsAuthenticated]
Thank You.

How to display form in django

I'am little confiused because my code in django does't work and I don't know why. I want to create a form displaying in html file. When I click on thh button, the url have to redirect me in the html file where I've put the form code. But the django return me a error
'User' object has no attribute 'nazwa_set'
My models.py is:
from django.db import models
from django.contrib.auth.models import User
class Firma(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Użytkownik")
nazwa = models.CharField(max_length=250,verbose_name='Nazwa firmy', unique=False)
class Meta:
verbose_name = 'Firmę'
verbose_name_plural = 'Firmy'
def __str__(self):
return self.nazwa
class Cudzoziemiec(models.Model):
OBYWATELSTWA = (
('RU', 'Rosja'),
('UA', 'Ukraina'),
('BY', 'Białoruś'),
)
TYTUL_POBYTOWY = (
('WZ', 'Wiza'),
('KP', 'Karta pobytu')
)
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Użytkownik")
nazwa = models.ForeignKey(Firma, on_delete=models.CASCADE, verbose_name="Firma")
obywatelstwo = models.CharField(max_length=250,choices=OBYWATELSTWA, verbose_name="Obywatelstwo")
imie = models.CharField(max_length=80, verbose_name="Imię", unique=False)
nazwisko = models.CharField(max_length=150, verbose_name="Nazwisko", unique=False)
data_ur = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data urodzenia")
miejsce_ur = models.CharField(max_length=100, verbose_name="Miejsce urodzenia")
paszport = models.CharField(max_length=30, verbose_name="Paszport")
data_start_pasz = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data wydania paszportu")
data_koniec_pasz = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data ważności paszportu")
dok_pobytowy = models.CharField(max_length=250,choices=TYTUL_POBYTOWY, verbose_name="Tytuł pobytowy")
data_start_pobyt = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Dokument pobytowy ważny od")
data_koniec_pobyt = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Dokument pobytowy ważny do")
class Meta:
verbose_name = 'Cudzoziemca'
verbose_name_plural = 'Cudzoziemcy'
def __str__(self):
return f'{self.imie} {self.nazwisko}'
in the view.py responsible def for adding the new record:
#login_required
def nowy_pracownik(request):
if request.method == "POST":
nowy_pracownik = CudzoziemiecForm(request.user, request.POST)
if nowy_pracownik.is_valid():
nowy_pracownik.save()
messages.success(request, 'Pomyślnie dodano pracownika !')
return render(request, 'cudzoziemiec/nowy_pracownik_ok.html')
else:
nowy_pracownik = CudzoziemiecForm(request.user)
return render(request, 'cudzoziemiec/nowy_pracownik.html', {'nowy_pracownik':nowy_pracownik})
And on the end here is my forms.py :
class FirmaForm(forms.ModelForm):
class Meta:
model = Firma
fields = ('nazwa',)
class CudzoziemiecForm(forms.ModelForm):
class Meta:
model = Cudzoziemiec
fields = ('nazwa','imie', 'nazwisko','obywatelstwo', 'data_ur','paszport', 'data_start_pasz', 'data_koniec_pasz', 'dok_pobytowy', 'data_start_pobyt', 'data_koniec_pobyt')
def __init__(self, user, *args, **kwargs):
super(CudzoziemiecForm, self).__init__(*args, **kwargs)
self.fields['nazwa'].queryset = user.nazwa_set.all()
self.user = user
def save(self, commit=True):
instance = super(CudzoziemiecForm, self).save(commit=False)
instance.user = self.user
if commit:
instance.save()
return instance
The error is probably somewhere in the forms. py in the class CudzoziemiecForm in line self.fields['nazwa'].queryset = user.nazwa_set.all()
In django default reverse lookup name is modelname_set. So when you trying to get user.nazwa_set.all() this means that there is some model Nazwa related with User. Since in your code you don't have model named Nazwa this line raise the error. I suppose you mean Cudzoziemiec or Firma so to fix problem you need to replace user.nazwa_set.all() with user.firma_set.all() in form's __init__ method.

How to get users profile in django 1.9

I have this method in my views.py file
def guest_login(request):
form = SomeForm(request.POST or None)
if form.is_valid():
email = request.POST['email']
password= request.POST['password']
u = authenticate(username = email, password = password)
if uis not None:
if u.is_active:
login(request, u)
userProfile= request.user.profile
return HttpResponseRedirect(userProfile.get_absolute_url())
else:
messages.error(request, 'Text', extra_tags='text')
else:
messages.error(request, 'Text', extra_tags='text')
else:
form = SomeForm()
context = {
"form": form,
}
return render(request, 'loginpage.html', context)
So, I did not extend the basic User, I created my own, and i did it like this:
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), max_length=255, db_index=True, blank = False, unique = True)
name= models.CharField(blank = False, max_length = 100)
surname= models.CharField(blank = False, max_length = 100)
# slug = models.SlugField(unique = True)
is_staff = models.BooleanField(
_('some_text'), default=False, help_text=_(
'text'))
is_active = models.BooleanField(_('ctive'), default=True, help_text=_(
'text'
'text'))
date_joined = models.DateTimeField(_('date created'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
# abstract = True
def get_full_name(self):
return self.name + " " + self.surname
def get_short_name(self):
return self.name
def get_email(self):
return self.email
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this User."""
send_mail(subject, message, from_email, [self.email], **kwargs)
class MyUserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
def get_absolute_url(self):
return reverse("user:restoraunts", kwargs={"slug": self.slug})
User.profile = property(lambda u: MyUser.objects.get_or_create(user=u)[0])
def create_slug(instance, new_slug=None):
slug = slugify(instance.user.name)
if new_slug is not None:
slug = new_slug
qs = MyUserProfile.objects.filter(slug=slug).order_by('-id')
exists = qs.exists()
if exists:
new_slug = "%s-%s" % (slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_guest_receiver(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
#
pre_save.connect(pre_save_guest_receiver, sender=MyUserProfile)
And in settings.py a added:
AUTH_USER_MODEL = 'korisnik.Korisnik'
AUTH_PROFILE_MODULE = 'korisnik.KorisnikProfil'
Everything works fine, except this line:
userProfile= request.user.profile
It says that "MyUser has no attribute profile".
I tried everything, get_profile(), get_profile, profile(), profile... Nothing worked. Can anyone help me? Thank you.
Note that the AUTH_PROFILE_MODULE setting and the get_profile() method where remove in django 1.7.
Try adding a related_name to your MyUserProfile.user field.
Also note that you might be able to just add that slug filed on the user model and avoid the extra relation.

Categories