How to set Foreign key to custom user model in CreateView? - python

I have this custom user model 'es_user'
models.py
class es_user(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class es_event(models.Model):
ev_name = models.CharField(max_length=100)
ev_venue = models.CharField(max_length=100)
ev_admin = models.ForeignKey('es_user',related_name='events',on_delete=None)
Eventually, I'll be adding more fields to es_user that's why I used a custom user model. So I cannot settle for django's inbuilt user model.
views.py
class CreateEventView(LoginRequiredMixin,CreateView):
model = es_event
fields = ['ev_name','ev_venue','ev_date','ev_description']
def form_valid(self, form):
form.instance.ev_admin = self.request.user
return super(CreateEventView, self).form_valid(form)
when I submit the form I get this error
Cannot assign "<SimpleLazyObject: <User: randy>>": "es_event.ev_admin" must be a "es_user" instance.
I've checked Django documentation and other stack overflow posts, but in all those the foreign key is referencing Django's inbuilt user model

So just assign the es_user, not the auth user.
form.instance.ev_admin = self.request.user.es_user

You can fetch the es_user instead:
form.instance.ev_admin = es_user.objects.get(user=self.request.user)

everything worked fine when I made some changes to views.py and models.py
views.py
class CreateEventView(LoginRequiredMixin,CreateView):
model = es_event
fields = ['ev_name','ev_venue','ev_date','ev_description']
def form_valid(self, form):
form.instance.ev_admin = self.request.user.es_user
models.py
class es_user(models.Model):
user = models.OneToOneField(User,related_name='es_user', on_delete=models.CASCADE)

Related

Save the data of current logged user in django

I am a newbie in django and I have a question about how I can save and show only the data of logged user - since my application is multi-tenant.
my view
class ProjetoCreate(CreateView):
model = Projeto
fields = ['nomeProjeto',
'descricao',
'dtInicio',
'deadline',
'nomeSprint',
'status',
]
def get_queryset(self):
logged_user = self.request.user
return Projeto.objects.filter(User=logged_user)
class ProjetoList(ListView):
paginate_by = 2
model = Projeto
my model
class Projeto(models.Model):
nomeProjeto = models.CharField(max_length=20)
descricao = HTMLField()
dtInicio = models.DateField(auto_now=False, auto_now_add=False)
deadline = models.DateField(auto_now=False, auto_now_add=False)
nomeSprint = models.CharField(max_length=30)
status = models.CharField(max_length=20)
Thank you very much!
Add
user = models.ForeignKey(User, on_delete=models.CASCADE)
to Projecto model. Then, in your view, set project.user = self.request.user before saving your project model.
I think you are doing it completely wrong.
You shouldn't be using get_queryset() at all in CreateView - https://stackoverflow.com/a/24043478/4626254
Here's is what you can try instead.
Add a user field in Project model and apply migrations.
user = models.ForeignKey(User, on_delete=models.CASCADE)
Create a class inheriting Generic APIView instead of CreateView.
Create a POST method like def post(self, request): inside that class and get all the details for creating a Projeto object in the request payload using request.data or request.POST.
Get the logged in user using request.user
Create a Projecto object with all this information as Projeto.objects.create(**your_other_fields, user=request.user)
Next time when filtering the objects, use a filter on user field like user=request.user.

Django: CreateView don't show field and set it to request.user (ForeignKey)

I use a generic CreateView to let logged in users (Creator) add objects of the model Piece. Since creating a Piece is done by the Creator (logged in user) there is no need for the CreateView to either show or manipulate the 'creator' field. Hence I wish to not show it and set it to the logged in user. However, approaches such as overwriting form_valid or using get_form_kwargs seem not to get it done. Using the form_valid method gives a ValueError:
Cannot assign "<SimpleLazyObject: <User: patrick1>>": "Piece.creator" must be a "Creator" instance.
The solution seems to be just around the corner, I hope.
Tried but did not work:
form_valid method, form_valid method, get_form_kwargs method
My code:
models.py
class Piece(models.Model):
creator = models.ForeignKey('Creator', on_delete=models.SET_NULL, null=True)
title = models.CharField(max_length=200)
summary = models.TextField(max_length=1000, help_text='Enter a brief description of the Piece')
created = models.DateField(null=True, blank=True)
...
from django.contrib.auth.models import User
class Creator(models.Model):
...
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
views.py
class PieceCreate(LoginRequiredMixin, CreateView):
model = Piece
fields = ['title', 'summary', 'created']
initial = {'created': datetime.date.today()}
def form_valid(self, form):
obj = form.save(commit=False)
obj.creator = self.request.user
return super(PieceCreate, self).form_valid(form)
success_url = reverse_lazy('pieces')
Any suggestions are highly appreciated!
obj.creator = Creator.objects.get(user=self.request.user)
or any other solution that will give you Creator instance for current user instead of User. Just as the error message says.
Cannot assign "User: patrick1": "Piece.creator" must be a "Creator" instance.

NOT NULL constraint failed: teams_team.user_id

When I submit a new team as a authenticated user, I get this error is showing. I searched a lot of answers but they say do it null=True or default=1 but I don't want to be it null or something I want to be user's id it. Plus I imported and tried settings.AUTH_USER_MODEL and get_user_model
from django.contrib.auth.models import User
#models.py
class Team(models.Model):
creator = models.ForeignKey(User, related_name='teams', on_delete=models.CASCADE)
name = models.CharField(max_length=20, unique=True)
rank = models.IntegerField(default=0)
#views.py
class TeamsCreateView(generic.CreateView):
model = Team
form_class = TeamCreationForm
#forms.py
class TeamCreationForm(forms.ModelForm):
class Meta:
model = Team
fields = ('name',)
Override the form_valid method, and set user on the form's instance before saving it.
from django.contrib.auth.mixins import LoginRequiredMixin
class TeamsCreateView(LoginRequiredMixin, generic.CreateView):
model = Team
form_class = TeamCreationForm
def form_valid(self, form):
form.user = self.request.user
return super(TeamsCreateView, self).form_valid(form)
Use LoginRequiredMixin to make sure that users can only access the view if they are logged in.

Django How can I save two different class which are connected each other by OneToOne relationship in a form at once?

Let me explain what my problem is in more detail.
First I have a class 'UserInfo' which connected to User class of django.contrib.auth.models like below
models.py
class UserInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=15,blank=True,unique=True)
position = models.CharField(max_length=15,blank=True,unique=True)
class Meta:
default_permissions = ()
def __str__(self):
return self.position
then I wanted to use ModelForm because I can write less codes. The reason why I made CreateNewUser class is that I wanted to let user can see only [username, email, groups, user_permissions] and control those. (to prevent them to select superuser or staff or inactive options)
forms.py
class CreateNewUserInfo(forms.ModelForm):
class Meta:
model = UserInfo
fields = '__all__'
class CreateNewUser(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'groups', 'user_permissions']
problem happened in here. I wanted to use FormView to use generic view with class typed view so that I can write less codes(concise code). there is attribute named 'form_class' and I couldn't put two different class with it. I wanted to put different two class to one form with generic view.
views.py
class TestView(FormView):
form_class = CustomForm
template_name = 'manager/alltoall.html'
def form_valid(self, form):
At the end, I made new class in forms.py and wrote every field which I need like below.
forms.py
class CustomForm(forms.Form):
username = forms.CharField(initial='testname',max_length=150)
email = forms.EmailField()
phone_number = forms.CharField(max_length=15)
position = forms.CharField(max_length=15)
views.py
class TestView(FormView):
form_class = CustomForm
template_name = 'manager/alltoall.html'
def form_valid(self, form):
username = form.cleaned_data['username']
email = form.cleaned_data['email']
phone_number = form.cleaned_data['phone_number']
position = form.cleaned_data['position']
with transaction.atomic():
user = User.objects.create(username=username,email=email)
userinfo = UserInfo.objects.create(user=user,phone=phone_number,position=position)
userinfo.save()
user.save()
return super(TestView, self).form_valid(form)
Is there anyway to use ModelForm and FormView to show two different class in a form at the same time? Additionally, I used transaction like above because I wanted to save data in database with two different class. Is it right approach or Is there any other way to do that more conveniently(or efficiently) with built in functions in django?
Thank you for taking your time to read all. I wonder if it is too long, but I wanted to deliver what I wanted to know exactly. Thank you!

Django: Set initial value for ForiegnKey in a CreateView

I'm trying to create a view of type CreateView. This view will take the form_class = CourseForm that I created and excluded some fields in it. The instructor field is a foriegnKey and I don't want the user to be able to control it in the form. It's a field that depends on the signed in user.
# forms.py
class CourseForm(forms.ModelForm):
class Meta:
model = Course
exclude = ['instructor', 'members', 'slug']
# ...
my view is as follows. I thought that by including the instructor value in initial would pass the profile instance when I submit
# views.py
#method_decorator(login_required, name='dispatch')
class CourseCreateView(CreateView):
model = Course
template_name = 'course_form.html'
success_url = reverse_lazy('course-create-complete')
form_class = CourseForm
def get_initial(self):
initial = super(CourseCreateView, self).get_initial()
initial = initial.copy()
profile = get_object_or_404(Profile, user__username=self.request.user)
initial['instructor'] = profile
return initial
# models.py
class Course(models.Model):
instructor = models.ForeignKey(Profile, related_name="Instructor")
# ... other fields
but the probelm is that whenever I submit the form I get the following error:
NOT NULL constraint failed: myapp_course.instructor_id
If you want to set the initial value of instructor field, you shouldn't exclude it from the form. You could instead make the field hidden.
Or you could include that in the exclude list, but then you shouldn't override get_initial method, but do the assignment manually:
class CourseCreateView(CreateView):
def form_valid(self, form):
self.object = form.save(commit=False)
# create instructor based on self.request.user
self.object.instructor = instructor
self.object.save()
return HttpResponseRedirect(self.get_success_url())
Check django doc about what does save(commit=False) do.
Also check django doc about form_valid function and how forms are handled in class based views.

Categories

Resources