I have a set a pre-existing teams that the user can join [team1, team2, team3] at /jointeam, and that will show up on /home.
My issue is that the variable 'user_team' from Profile stays 'None', even after the user successfully joins a team.
In other words, if I enter 'team1' on /jointeam , I'd like it to assign it to user.profile.user_group
Thanks in advance, appreciate your input!
Here is my code:
Models.py
#used to create a team
class TeamCreation(models.Model):
team_name = models.CharField(max_length=100, default=None, unique=True)
[...]
def __str__(self):
return self.team_name
#user-specific
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_team = models.CharField(max_length=30, null=True)
[...]
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
#model to join a team
class Join(models.Model):
team_name = models.CharField(max_length=100, default=None, unique=False)
def __str__(self):
return self.team_name
Forms.py
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email']
class TeamCreationForm(forms.ModelForm):
class Meta:
model = TeamCreation
fields=['team_name']
class JoinForm(forms.ModelForm):
class Meta:
model = Join
fields=['team_name']
views.py - users
[...]
#login_required
def join_team(request):
form_class = JoinForm
form_join = form_class(request.POST or None)
user = request.user
if request.method=='POST':
if form_join.is_valid():
newJoin = form_join.save(commit=False)
if not TeamCreation.objects.filter(team_name=newJoin.team_name).exists():
print("nope")
return redirect('dashboard')
messages.error("Team doesn't exist or incorrect key")
else:
print("exist")
group_name=newJoin.team_name
user.profile.user_team=group_name
newJoin.save()
return redirect('dashboard')
else:
print("Error")
context={
"form":form_join,
}
return render(request, "pages/join_team.html", context)
#login_required
def home(request):
user = request.user
group_name=user.profile.user_team
context={
"user_group":group_name,
}
return render(request,'pages/dashboard.html', context)
Home.html
[...]
{% if user_team %}
<option>{{ user_team }}</option>
<option>Join a team</option>
<option>Create a team</option>
{% else %}
<option>-- none</option>
<option>Join a team</option>
<option>Create a team</option>
{% endif %}
[...]
You need to save the profile after updating it.
group_name = newJoin.team_name
newJoin.save()
user.profile.user_team = group_name
user.profile.save()
It's probably a better idea to save the profile after the join instance has been created in case it fails.
Related
I am currently trying to create a form where users get to fill in their details after creating an account. The idea is that every user, after registration, gets redirected to this form page to fill it out. To achieve this, i'm using foreign keys.However it doesn't save to database.
models.py
class User(AbstractUser):
pass
def __str__(self):
return self.username
class Detail(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, default="")
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=255, default="")
class Meta:
verbose_name_plural = "Detail"
def __str__(self):
return self.first_name+ " "+self.last_name
forms.py
class Details(forms.ModelForm):
class Meta:
model = Detail
fields = "__all__"
widgets={
"user": forms.TextInput()
}
views.py
def details(request):
if request.method =="POST":
form = Details(request.POST)
if form.is_valid():
detail = form.save(commit=False)
detail.user = request.user
detail.first_name = detail.first_name.lower()
detail.last_name = detail.last_name.lower()
detail.save()
return redirect("admin:index")
else:
form = Details(initial={"user":request.user.username})
return render(request, "details.html", {"form":form})
You need to exclue user field from ModelForm like this
form.py
class Details(forms.ModelForm):
class Meta:
model = Detail
fields = "__all__"
exclude =["user"]
views.py
def details(request):
if request.method =="POST":
form = Details(request.POST)
if form.is_valid():
detail = form.save(commit=False)
detail.user = request.user
detail.first_name = detail.first_name.lower()
detail.last_name = detail.last_name.lower()
detail.save()
return redirect("admin:index")
else:
form = Details()
return render(request, "details.html", {"form":form})
I have a django UpdateView which needs to inherit three different models and different models. CreateView is working fine with three different modelforms.
models.py:
class Employee(models.Model):
"""
Create employee attributes
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
e_id = models.IntegerField(unique=True, null=True, blank=True)
first_name = models.CharField(max_length=128,blank=True)
last_name = models.CharField(max_length=128, blank=True)
.....
class WorkExperience(models.Model):
"""
Stores employee previous work experiences
"""
employee = models.ForeignKey('Employee', related_name='we_employee', on_delete=models.CASCADE, null=True)
previous_company_name = models.CharField(max_length=128, null=True)
job_designation = models.CharField(max_length=128, null=True)
from_date = models.DateField(null=True)
......
class Education(models.Model):
"""
Stores employee education background
"""
employee = models.ForeignKey('Employee', related_name='edu_employee', on_delete=models.CASCADE, null=True)
institution_name = models.CharField(max_length=128, null=True)
degree = models.CharField(max_length=128, null=True)
.....
views.py:
class EmployeeUpdateView(LoginRequiredMixin,UpdateView):
"""
Update a created a employee
"""
login_url = '/authentication/login/'
template_name = 'employee/employee_add_form.html'
form_class = EmployeeAddModelForm
work_form_class = WorkExperienceForm
education_form_class = EducationForm
queryset = Employee.objects.all()
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
def get_object(self):
id_ = self.kwargs.get("id")
return get_object_or_404(Employee, id=id_)
WHen I go to Update view, I am only able to update EmployeeAddModelForm values. But other form's(WorkExperienceForm, EducationForm ) fields do not appear let alone edit the values of the fields.
I suppose my views.py is not correct.
I need suggestion to correct my updateview.
If you want to put multiple forms in one HTML file, in my way, write as follows.
class EmployeeUpdateView(LoginRequiredMixin,UpdateView):
login_url = '/authentication/login/'
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
def get(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
user = Employee.objects.get(id=id_)
work = WorkExperience.objects.get(employee=user)
education = Education.objects.get(employee=user)
return render(request, self.template_name, {
'form': EmployeeAddModelForm(instance=user),
'work_form': WorkExperienceForm(instance=work),
'education_form': EducationForm(instance=education)
}
)
def post(self, request):
first_name = request.POST['first_name']
# Your own code...
.....
I think the argument of each form depends on the definition of Form.
And in a very simple way, the HTML file looks like this:
<body>
<form method="post">
{% csrf_token %}
{{ employ_form }}
{{ work_form }}
{{ edu_form }}
<button type="submit">OK</button>
</form?
</body>
</html>
I'm not sure if this is the best option.
How about putting forms into get_context_data?
Something like
context['form1'] = EmployeeAddModelForm()
context['form2] = WorkExperienceForm()
Etc.
Edit:
def get_context_data(self, **kwargs):
context = super(EmployeeUpdateView, self).get_context_data(**kwargs)
context['form'] = EmployeeAddModelForm()
context['form2'] = WorkExperienceForm()
context['form3'] = EducationForm()
return context
I created a field in my signup form asking users for a link to their linkedin profile.
I created a page that returns a list of all the users (mentor users) and noticed that I cannot access the linkedin link. I am not sure if its because I have not saved the link or I am not accessing it correctly.
This is what I have in models.py
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
...
class Mentor(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
linkedin = models.URLField(max_length=200,null=True,blank=True)
def __str__(self):
return "Profile of user {}".format(self.user.username)
#receiver(post_save,sender=User)
def create_or_update(sender, instance, created, **kwargs):
if created:
post_save.connect(create_or_update, sender=User)
forms.py
class TeacherSignUpForm(UserCreationForm):
email = forms.EmailField(max_length=100)
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
linkedin = forms.URLField(max_length=200)
class Meta(UserCreationForm.Meta):
model = User
fields = ('email', 'username', 'first_name', 'last_name')
def save(self, commit=True):
self.instance.is_teacher = True
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
mentor = Mentor.objects.get_or_create(
user=user,
linkedin=self.cleaned_data['linkedin']
)
return user
#basic form
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
views.py (teachers.py)
class TeacherSignUpView(CreateView):
model = User
form_class = TeacherSignUpForm
template_name = 'registration/signup_form.html'
def get_context_data(self, **kwargs):
kwargs['user_type'] = 'teacher'
return super().get_context_data(**kwargs)
def form_valid(self, form):
user = form.save()
login(self.request, user)
return redirect('teachers:app-instructor-dashboard')
students.py (views)
#get list of mentors
def mentor_list(request):
mentors = User.objects.filter(is_teacher=True).select_related('mentor')
template_name = 'classroom/students/mentor_list.html'
context = {'mentors': mentors}
return render(request, template_name, context)
the html where I generate the list of mentors:
<ul id="menu-header-menu">
{% for user in mentors %}
<li>{{ user.first_name }} {{ user.last_name }}</li>
{% endfor %}
</ul>
From this list I only get the user's first and last name but cannot get their linkedin profile
You have use mentor in this line mentors = User.objects.filter(is_teacher=True).select_related('mentor') but not defined mentor anywhere.
Table are connected with this line:
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
add related_name .
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True, related_name='mentor')
Then makemigrations and migrate(I Hope you are familiar). Everything else is fine.
Also, print this to verify.
def mentor_list(request):
mentors = User.objects.filter(is_teacher=True).select_related('mentor')
# Edited, remember this is just for checking. this is not required
for user in mentors:
try:
print(user.mentor.linkedin)
except:
pass
template_name = 'classroom/students/mentor_list.html'
context = {'mentors': mentors}
return render(request, template_name, context)
I have a little problem. I want to to display in list only records belongs to user whos add it. In my app when I'am login as 'user' and I want to add new records incude records from list, I see all records in db from ForeignKey. How to make it correctly?
In 'Strona www' when I expand the list I see all records, not only records added by user personally.
My view for it is:
#login_required
def new_keyword(request):
if request.method == "POST":
new_keyword = KeywordForm(request.POST)
if new_keyword.is_valid():
new_keyword=new_keyword.save(commit=False)
new_keyword.user = request.user
new_keyword.save()
messages.success(request, 'Pomyślnie dodano słowo kluczowe')
return render(request, 'konto/new_keyword_ok.html')
else:
new_keyword = WebsiteForm()
return render(request, 'konto/new_keyword.html', {'new_keyword':new_keyword})
in forms.py I have:
class KeywordForm(forms.ModelForm):
class Meta:
model = Keyword
fields = ('www', 'keyword')
models.py
class Keyword(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Użytkownik")
www = models.ForeignKey(Website, on_delete=models.CASCADE, verbose_name="Strona www")
keyword = models.CharField(max_length=250, verbose_name="Słowo kluczowe", unique=False)
urls.py
path('new-keyword/', new_keyword, name='new_keyword'),
and html for display the form is:
{% if request.user.is_authenticated %}
<form action="." method="post">
{{ new_keyword.as_p }}
{% csrf_token %}
<p><input type="submit" value="Dodaj nowe słowo kluczowe" ></p>
Powrót do monitoringu
</form>
{% endif %}
EDIT:
models.py
from django.db import models
from django.contrib.auth.models import User
class Website(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Użytkownik")
website = models.CharField(max_length=250,verbose_name='Strona www', unique=False)
class Meta:
verbose_name = 'Strona www'
verbose_name_plural = 'Strony www'
def __str__(self):
return self.website
class Keyword(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Użytkownik")
www = models.ForeignKey(Website, on_delete=models.CASCADE, verbose_name="Strona www")
keyword = models.CharField(max_length=250, verbose_name="Słowo kluczowe", unique=False)
class Meta:
verbose_name = 'Słowo kluczowe'
verbose_name_plural = 'Słowa kluczowe'
def __str__(self):
return self.keyword
Pass the request.user to your form and use the inverse relation user.website_set :
forms :
class KeywordForm(forms.ModelForm):
class Meta:
model = Keyword
fields = ('www', 'keyword')
def __init__(self, user, *args, **kwargs):
super(KeywordForm, self).__init__(*args, **kwargs)
self.fields['www'].queryset = user.website_set.all()
self.user = user
def save(self, commit=True):
instance = super(KeywordForm, self).save(commit=False)
instance.user = self.user
if commit:
instance.save()
return instance
views:
#login_required
def new_keyword(request):
if request.method == "POST":
new_keyword = KeywordForm(request.user, request.POST)
if new_keyword.is_valid():
new_keyword.save()
messages.success(request, 'Pomyślnie dodano słowo kluczowe')
# DONT DO THIS ! REDIRECT INSTEAD
return render(request, 'konto/new_keyword_ok.html')
else:
new_keyword = KeywordForm(request.user)
return render(request, 'konto/new_keyword.html', {'new_keyword':new_keyword})
As a side note: after a successful POST you want to redirect (even if to the same url). This avoids a lot of troubles (and duplicate submissions) when a user reloads the page
Just pass the user id to your form and then set a queryset for your field
like this:
How to pass the user to your form:
in your view:
#login_required
def new_keyword(request):
if request.method == "POST":
#### Notice this part.
new_keyword = KeywordForm(data=request.POST, u=request.user)
if new_keyword.is_valid():
new_keyword=new_keyword.save(commit=False)
new_keyword.user = request.user
new_keyword.save()
messages.success(request, 'Pomyślnie dodano słowo kluczowe')
return render(request, 'konto/new_keyword_ok.html')
else:
# Notice this part.
new_keyword = WebsiteForm(data=None, u=request.user)
return render(request, 'konto/new_keyword.html', {'new_keyword':new_keyword})
How to retrieve the user in form and set the queryset:
forms.py:
class KeywordForm(forms.ModelForm):
class Meta:
model = Keyword
fields = ('www', 'keyword')
def __init__(self, current_user, *args, **kwargs):
self.u = kwargs.pop("u") ## The user you just passed.
super(KeywordForm, self).__init__(*args, **kwargs)
self.fields['www'].queryset = Website.objects.filter(user=self.u) ## Setting the queryset.
I just want to filter select field in a form, regarding a currently logged user. Every user has own categories and budgets - I want to display only a models related with a currently logged user. I've tried stuff with filtering before is_valid field, but with no result. Please, find my code below:
views.py
#login_required
def day_data_multiadd(request, no_of_lines=0):
no_of_lines = int(no_of_lines)
CostFormSet = modelformset_factory(Cost, form=DataAddForm, extra=no_of_lines)
if request.method == 'POST' and 'form' in request.POST:
formset = CostFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.forms:
f = form.save(commit=False)
f.user = request.user
f.save()
else:
formset = CostFormSet(queryset=Cost.objects.none())
if request.method == 'POST' and 'no_line' in request.POST:
generate_form = MultiaddGenerateForm(request.POST)
if generate_form.is_valid():
cd = generate_form.cleaned_data
return HttpResponseRedirect(reverse('core_sm:day_data_multiadd', args=(cd['formy'], )))
else:
generate_form = MultiaddGenerateForm()
return render(request, 'core_sm/costs/multi_add.html', {'formset': formset,
'no_of_lines': no_of_lines,
'generate_form': generate_form})
forms.py
class DataAddForm(forms.ModelForm):
class Meta:
model = Cost
fields = ['title', 'value', 'publish', 'category', 'budget']
exclude = ['user']
labels = {
'title': _('Tytuł'),
'value': _('Wartość'),
'publish': _('Data'),
'category': _('Kategoria'),
'budget': _('Budżet')
}
models.py
class Category(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200)
publish = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_ur(self):
return reverse('core_sm:category_detail', args=[self.id])
class Budget(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200, db_index=True)
value = models.DecimalField(decimal_places=2, max_digits=10)
publish = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('core_sm:budget_detail', args=[self.id])
class Cost(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
budget = models.ForeignKey(Budget, related_name='cost')
category = models.ForeignKey(Category, related_name='cost')
title = models.CharField(max_length=200, db_index=True)
publish = models.DateField(default=timezone.now)
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
value = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
ordering = ('-publish',)
def get_absolute_url(self):
return reverse('core_sm:stats_detail', args=[self.publish.year,
self.publish.strftime('%y'),
self.publish.strftime('%m'),
self.publish.strftime('%d')])
def __str__(self):
return self.title
According to the docs you can pass custom parameters to formsets forms.
class DataAddForm(forms.ModelForm):
class Meta:
model = Cost
fields = ['title', 'value', 'publish', 'category', 'budget']
exclude = ['user']
labels = {
'title': _('Tytuł'),
'value': _('Wartość'),
'publish': _('Data'),
'category': _('Kategoria'),
'budget': _('Budżet')
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
self.fields['category'].queryset = Category.objects.filter(user=user)
self.fields['budget'].queryset = Budget.objects.filter(user=user)
super(DataAddForm, self).__init__(*args, **kwargs)
views.py
formset = CostFormSet(queryset=Cost.objects.none(), form_kwargs={'user': request.user})