Populating a FormView with custom queryset - django

I'd like to set the logged in user's data to a profile form. Why isn't the below view populating the model form?
class UpdateProfile(FormView):
model = User
form_class = ProfileForm
def get_queryset(self):
return self.model.objects.get(pk=self.request.user.id)
class ProfileForm(forms.ModelForm):
class Meta:
model = User
fields = ['email', 'name', 'company', 'title']
All my fields end up empty.

For single object views, you need to override get_object and use an UpdateView.
So to get the logged in user you could do:
from django.views.generic import UpdateView
class UpdateProfile(UpdateView):
model = User
form_class = ProfileForm
def get_object(self):
return self.request.user

Related

Use Form.has_changed() validation with Django UpdateView

I am trying to post a message when one or more of the values have changed in an UpdateView. Is this possible to do with Form.has_changed() with this generic view? For example:
class MyUpdateView(UpdateView):
model = MyModel
form = MyModelForm
fields = "__all__"
template_name = "mymodel_form.html"
if form.has_changed():
logger.info("Some values have changed")
You can override the .form_valid(…) method [Django-doc] for this:
class MyUpdateView(UpdateView):
model = MyModel
form_class = MyModelForm
fields = '__all__'
template_name = 'mymodel_form.html'
def form_valid(self, form):
if form.has_changed():
logger.info('Some values have changed')
return super().form_valid(form)
or if you want to log changes if the form might be invalid as well, you can use .get_form(…) [Django-doc]:
class MyUpdateView(UpdateView):
model = MyModel
form_class = MyModelForm
fields = '__all__'
template_name = 'mymodel_form.html'
def get_form(self, form_class=None):
form = super().get_form(form_class=form_class)
if form.has_changed():
logger.info('Some values have changed')
return form

Django DetailView form dont save data

I have a DetailView, and need add a form to user contact.
views.py
class ProductView(FormView, DetailView):
model = Product
template_name = 'product_detail.html'
form_class = NotificationForm
success_url = '/products/'
def post(self, request, *args, **kwargs):
return FormView.post(self, request, *args, **kwargs)
forms.py
class NotificationForm(ModelForm):
..."""some fields"""
class Meta:
model = Notification
fields = [
'usernameclient',
'emailclient',
'emailclient_confirmation',
'phoneclient',
'messageclient',
]
The model Notification is where is stored the data from that form
models.py
class Notification(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
..."""some fields"""
I dont understand yet how django workflow with forms. After the submition is correct rediretc to success_url, but nothing is save in db... What is missing?
A FormView does not save the form, a CreateView does. You can save the form with:
class ProductView(FormView, DetailView):
model = Product
template_name = 'product_detail.html'
form_class = NotificationForm
success_url = '/products/'
def form_valid(self, form):
form.save()
return super().form_valid(form)

Save form data to database

I am new in Django and I really need help,
I do not know how to save my form data to database. I have problem to views.py
I will user's id who filled the form added into the foreign key field.
If there is any link or example that help me I appreciate you.
# views.py
#login_required(login_url="home")
def melk_new(request):
form = MelkForm()
???
return render(request, 'melk_new.html',{'form': form})
# models.py
class Melk(models.Model):
category = models.CharField(max_length=50)
city = models.CharField(max_length=100)
person = models.ForeignKey('CustomUser', on\_delete=models.CASCADE)
def \_\_str\_\_(self):
return self.category
class CustomUser(AbstractUser):
def __str__(self):
return self.email
---------------------------------------------------------------------------
# forms.py
class MelkForm(forms.ModelForm):
class Meta:
model = Melk
fields = ('category', 'city')
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
To get the currently logged in user you'll find it within request.user object. but before you assume that there is a currently logged in user, you need to validate that so you have 2 widely known options:
request.user.is_authenticated()
#login_required() decorator used if you from django.contrib.auth.decorators import login_required
if request.user.is_authenticated():
Car.objects.create(model_id=some_id, person=request.user)
Note:
The #login_required() is added above the function
#login_required(login_url="home")
def melk_new(request):
form = MelkForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.user_id = request.user.id
instance.save()
return render(request,'melk_new.html', { 'form': form})

OneToOne relation and NestedSerializer issue about User model

I'm trying to do a login app including registration, authentication etc...
I'm getting this error:
AttributeError: Got AttributeError when attempting to get a value for field 'user' on serializer 'PictureUserSerializer'.
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'.
But, when I check my admin page. The user has been registered with the right informations. I'm not feeling like this error come from nowhere and I must do something wrong. Here is my code:
logginapp/models.py
from django.db import models
from django.contrib.auth.models import User
class PictureUser(models.Model):
user = models.OneToOneField(User) #OneToOne link to the Django's User Model
avatar = models.ImageField(null=True, blank=True, upload_to="avatars/")
def username(self, user):
return user.username
def password(self, user):
return user.password
def email(self, user):
return user.email
loginapp/serializer.py
from django.core.validators import validate_email
from django import forms
from rest_framework import serializers
from loginapp.models import PictureUser
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email')
write_only_fields = ('password',)
class PictureUserSerializer(serializers.ModelSerializer):
"""
Serializer to put the PictureUser model into JSON
"""
user = UserSerializer()
class Meta:
model = PictureUser
fields = ('user', 'avatar')
read_only_fields = ('created',)
def create(self, validated_data):
print (validated_data)
return User.objects.create_user(validated_data['user']['username'], validated_data['user']['email'],
validated_data['user']['password']
)
loginapp/view.py
from django.shortcuts import render
from rest_framework import generics
from .serializer import PictureUserSerializer
from .models import PictureUser
class PictureUserCreateView(generics.ListCreateAPIView):
"""
This class define the Create behaviour of a PictureUser
"""
queryset = PictureUser.objects.all()
serializer_class = PictureUserSerializer
def perform_create(self, serializer):
serializer.save()
If you need to create user from PictureUserSerializer, then,
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create_user(**user_data)
return PictureUser.objects.create(user = user, **validated_data)
PictureUserSerializer create method needs to return a PictureUser instance, not a User instance.

How to implement serializing for nested objects

Had implemented a basic authentication system using function based views in django.
Trying to upgrade it to class based views.
Creating a UserProfile by inheriting from a django User model.
Need to serialize UserProfile and return to client side
User model :
from django.contrib.auth.models import User
UserProfile model :
class UserProfile(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
profile_picture = models.ImageField(upload_to='documents', blank=True)
def __str__(self):
return self.user.username
UserSerializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','password', 'first_name', 'last_name', 'email',)
write_only_fields = ('password',)
read_only_fields = ('is_staff', 'is_superuser', 'is_active', 'date_joined',)
def restore_object(self, attrs, instance=None):
user = super(UserSerializer, self).restore_object(attrs, instance)
user.set_password(attrs['password'])
return user
UserProfileSerializer:
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = ('id','user','profile_picture',)
views.py:
class AuthView(APIView):
authentication_classes = (BasicAuthentication,)
def post(self, request, *args, **kwargs):
login(request, request.user)
content={ 'user':UserProfileSerializer(request.user).data,'token':csrf.get_token(request)}
return Response(content)
UserProfileSerializer(request.user).data in views.py is not working.
but instead if i use:
UserSerializer(request.user).data, it gives me result(as expected) :
{'first_name': '', 'username': 'admin', 'email': 'a#a.com', 'last_name': '', 'password': 'pbkdf2_'}
But i also want additional attributes to the user also serialized like profile_picture, hence something like
UserProfileSerializer(request.user).data
should work for me.
Questions:
Is it possible to serialize a model containing FileField ?
How to serialize a nested object and return its data ?
Kinda beginner here.
yes it is possible to serialize a FileField. The problem is that your profile serializer needs a UserProfile model and not a User model. Try this:
content={ 'user':UserProfileSerializer(request.user.user_profile).data,'token':csrf.get_token(request)}