Django - How add a user to a group with Class Based View - django

I'm having some issues trying to add a user to specific group with generic CreateView.
The trouble is that i want that only one user creates the user's accounts and assign him to a group
The form is rendering correctly and it seems select the correct group without issue, but when i check the user doesn't have any group assigned. I tried many ways that i sow but any seems work for me.
I dont know if i should do it in (Post method), or form_valid()
Im using the CreateView but I'm not so good modifying the class it self,
Please any help
Im using the default user and this is my create class
Views.py
class CreateUserView(LoginRequiredMixin, CreateView):
model = User
form_class = CustomUserForm
template_name = 'accounts/create_user.html'
queryset = User.objects.all()
def get_success_url(self):
return reverse_lazy('accounts:list_user')
def post(self, request, *args, **kwargs):
if self.request.method == 'POST':
form = self.form_class(self.request.POST)
if form.is_valid():
self.object = form.save(commit=False)
# form_class = self.get_form_class()
# form = self.get_form(form_class)
# position = int(request.POST['groups'])-1
# self.object.groups.add(position)
my_group = Group.objects.get(name="Usuario Avanzado")
my_group.user_set.add(self.object)
self.object.save()
return HttpResponseRedirect(self.get_success_url())
return HttpResponseRedirect(self.get_success_url())
Please any help I'll be so grateful

Take reference from this. In this whenever new member is created it will assign that member to Society group
def User_registration(sender,instance,created,**kwargs):
if created:
print('Created')
member = Group.objects.get(name = 'Society') #Society is Group name
instance.groups.add(member)
print('Member created')
post_save.connect(User_registration,sender=User)

Visit for more detail:https://www.benlopatin.com/using-django-proxy-models/
#Main Model
class SocietyUser(AbstractBaseUser,PermissionsMixin):
class Types(models.TextChoices):
MEMBER = "MEMBER", "Member"
GATEKEEPER = "GATEKEEPER", "Gatekeeper"
base_type = Types.MEMBER
type = models.CharField(
_("Type"), max_length=50, choices=Types.choices, default=base_type
)
society = models.ForeignKey(Society,null=True, blank =True,on_delete=models.CASCADE)
society_user = models.CharField(max_length=200,unique=True)
email = models.EmailField(_('email address'),unique=True)
name = models.CharField(max_length=200,default=None)
created_date = models.DateTimeField(default=timezone.now)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = CustomSocietyManager()
USERNAME_FIELD = 'society_user'
REQUIRED_FIELDS = ['society','name','email']
def __str__(self):
return self.society_user
#ProxyModels
class Member(SocietyUser):
objects = MemberManager()
class Meta:
proxy = True
permissions = (
('view_content', 'View content'),
('change_visitor', 'can change content'),
)
class Gatekeeper(SocietyUser):
objects = GatekeeperManager()
class Meta:
proxy = True
#signals
def member_registration(sender,instance,created,**kwargs):
if created:
print('Created')
member = Group.objects.get(name = 'Society')
instance.groups.add(member)
print('Member created')
post_save.connect(member_registration,sender=Member)
def gatekeeper_registration(sender,instance,created,**kwargs):
if created:
print('Created')
gatekeeper = Group.objects.get(name = 'Gatekeeper')
instance.groups.add(gatekeeper)
print('Gatekeeper created')
post_save.connect(gatekeeper_registration,sender=Gatekeeper)

Related

How to assign model form field to a current logged in user in Django's class based views

I am trying to save a form with the current logged in user's username, but the error "Cannot assign "'Neshno_Games2'": "League.host" must be a "Manager" instance." occurs
Views.py
class CreateLeaguesView(generic.CreateView):
model = League
template_name = "leagues/create-league.html"
form_class = LeaguesCreationForm
success_url = "/leagues/leagues"
def get_context_data(self, **kwargs):
context = super().get_context_data( **kwargs)
context['leagues'] = League.objects.all()
return context
def form_valid(self, form):
manager = self.request.user.username
League.objects.create(
host = manager,
)
return super(CreateLeaguesView, self).form_valid(form)
Model.py
class League(models.Model):
name = models.CharField(max_length=30)
no_players = models.IntegerField(default=20)
start_date = models.DateField(blank=False, null=False)
end_date = models.DateField(blank=False, null=False)
prize = models.CharField(max_length=300)
host = models.ForeignKey(Manager, on_delete=models.CASCADE)
def __str__(self):
return self.name
forms.py
class LeaguesCreationForm(forms.ModelForm):
class Meta:
model = League
fields = (
"name",
"no_players",
"start_date",
"end_date",
"prize",
)
You can try like this:
class CreateLeaguesView(generic.CreateView):
model = League
def form_valid(self, form):
form.instance.host= self.request.user.manager # accessing one to one data
return super().form_valid(form)
More information can be found here in this documentation: https://docs.djangoproject.com/en/4.0/topics/db/examples/one_to_one/

How to get all form field data in Django UpdateView when working with many-to-many model field?

For some reason my UpdateView is not displaying the selected associated. The form is pre-populated with only the first form field data results, username, and none of the other field data. I suspect this is due to the ManytoMany field being queried. I've searched for and tried possible solutions but nothing has worked. Any ideas?
Models.py
class Company(models.Model):
"""All company specific details. For each main manager, a company is created. The main manager can then add company members, creating for them their user accounts."""
members = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name='teams', through='CompanyMembership'
)
...
class CompanyMembership(models.Model):
"""Acts as a gateway between User model and Company model"""
STAFF = "STAFF", "Staff"
MANAGERS = "MANAGERS", "Managers"
my_company = models.ForeignKey(Company, on_delete=models.CASCADE)
my_identity = models.ForeignKey(User, on_delete=models.CASCADE)
my_role = models.CharField(max_length=100, choices=MemberTypes.choices, default=None)
class User(models.Model):
"""Users can be main managers or staff. Each main manager has their own Company. Many staff can belong to a single Company associated with a main manager."""
username = models.CharField(_("Login Name"), blank=True, null=True, max_length=155, unique=True)
...
Views.py
class TeamMembersView(LoginRequiredMixin, CompanyMembershipCheckMixin, UserPassesTestMixin, ListView):
"""Lists all the company team members for the specific company"""
model = Company
template_name = 'users/dashboard/team.html'
def test_func(self):
user_obj = User.objects.get(id=self.request.user.id)
return user_obj.groups.filter(name='Company_Main_Manager').exists()
def get_context_data(self, **kwargs):
context = super(TeamMembers, self).get_context_data(**kwargs)
user_obj = User.objects.get(id=self.request.user.id)
companymembership_obj = CompanyMembership.objects.get(my_identity=user_obj)
company_obj = Company.objects.get(id=companymembership_obj.my_company.id)
slug = company_obj.slug
context['members'] = ecosystem_obj.members.all()
context['slug'] = slug
return context
class TeamMemberUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
"""Allows the main manager to change or update the specific staff member's user data"""
model = User
template_name = 'users/dashboard/user_create.html'
form_class = TeamMemberCreateForm
def test_func(self):
user_obj = User.objects.get(id=self.request.user.id)
return user_obj.groups.filter(name='Company_Main_Manager').exists()
def get_context_data(self, **kwargs):
data = super(TeamMemberUpdateView, self).get_context_data(**kwargs)
if self.request.POST:
data['member'] = TeamMemberCreateForm(self.request.POST, self.request.FILES)
else:
data['member'] = TeamMemberCreateForm()
return data
def form_valid(self, form):
context = self.get_context_data()
member = context['member']
with transaction.atomic():
form.instance.created_by = self.request.user
self.object = form.save()
if member.is_valid():
member.instance = self.object
member.save()
return super(TeamMemberUpdateView, self).form_valid(form)
Forms.py
class TeamMemberCreateForm(ModelForm):
"""Allows the main manager to create (and update) a user account for additional staff members."""
first_name = forms.CharField(max_length=200, help_text="Enter member's first name", required=True)
last_name = forms.CharField(max_length=200, help_text="Enter member's last name")
email = forms.EmailField(max_length=200, help_text="Member's primary email address")
phone = forms.CharField(max_length=100, help_text="Primary phone number")
position_title = forms.CharField(max_length=200, help_text="Member's job position or title for the company")
class Meta(UserCreationForm.Meta):
model = User
exclude = ['company_name']
#transaction.atomic
def save(self):
member_user = super().save(commit=False)
member_user.firstname = self.cleaned_data.get('first_name')
member_user.lastname = self.cleaned_data.get('last_name')
member_user.email = self.cleaned_data.get('email')
member_user.phone = self.cleaned_data.get('phone')
member_user.is_company_main_manager = False
member_user.is_active = True
member_user.user_type = User.UserTypes.STAFF
member_user.save()
CompanyMembership.objects.create(my_company=ecosystem_create, my_identity=user, my_role=CompanyMembership.MemberTypes.STAFF)
return member_user
As an example, if I am the main manager I can create a user account for my staff member through the above form. For the staff member account I enter username="username_example", first_name="pete", last_name="smith", phone="333-333-3333",... and so on. CreateView works as expected. The user account is created, saved, etc. UpdateView, though, display would show in this example:
username: username_example
first name:
last name:
phone:
...
# The first field of the form is pre-populated but none of the others... why?
You have to super init your form and rewrite the field with the
def init(self, *args, **kwargs):
super(TeamMemberCreateForm, self).__init__(*args, **kwargs)
self.fields[your_field] = forms.ModelMultipleChoiceField(
queryset=Company.objects.all(),
widget=forms.CheckboxSelectMultiple(attrs=
{'dir': 'ltr', 'type': "checkbox",'switch':"bool"}))
By using fields = ['username', 'firstname', 'lastname', 'email', 'phone'] instead of form_class = TeamMemberCreateForm in UpdateView, the problem was solved.

Django modelforms, foreignkey filter for data owned by logged in user [duplicate]

I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .

Django - How to add sender-name in Email?

What I am trying to achieve is having the senders-name, from the current logged in user with the association name, to show up in the receivers inbox like so:
'associaton-name'#domain.com
I have commented it down below where i tried to achieve it in views.py
Can't seem to find any related solutions after days and hours of work.
Really appreciate your help, folks!
Django: 1.10
Python: 3.6
views.py
class mailPost(FormView):
success_url = '.'
form_class = mailHandler
template_name = 'post/post.html'
def form_valid(self, form):
messages.add_message(self.request, messages.SUCCESS, 'Email Sent!')
return super(mailPost, self).form_valid(form)
def form_invalid(self, form):
messages.add_message(self.request, messages.WARNING,
'Email not sent. Please try again.')
return super(mailPost, self).form_invalid(form)
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
sender = "noreply#domain.com" # Instead of noreply I wish for current requested associaton name
receiver = form.cleaned_data.get('receiver')
cc = form.cleaned_data.get('cc')
bcc = form.cleaned_data.get('bcc')
subject = form.cleaned_data.get('subject')
message = form.cleaned_data.get('message')
time = datetime.now()
asoc_pk = Association.objects.filter(asoc_name=self.request.user.association)
asoc = Association.objects.get(id=asoc_pk)
Email.objects.create(
sender=sender,
receiver=receiver,
cc=cc,
bcc=bcc,
subject=subject,
message=message,
association=asoc,
sentTime=time
)
msg = EmailMultiAlternatives(subject, message, sender, [receiver], bcc=[bcc], cc=[cc])
msg.send()
return self.form_valid(form)
else:
return self.form_invalid(form)
models.py
class Email(models.Model):
sender = models.CharField(max_length=254)
sentTime = models.DateTimeField(auto_now_add=True, blank=False)
subject = models.CharField(max_length=254)
receiver = models.CharField(max_length=254)
cc = models.CharField(max_length=254)
bcc = models.CharField(max_length=254)
message = models.TextField()
association = models.ForeignKey(Association)
class Meta:
db_table = 'Email'
class Association(models.Model):
asoc_name = models.CharField(max_length=50, null=True, blank=True, unique=True)
class Meta:
db_table = 'Association'
class Administrator(AbstractUser):
...
association = models.ForeignKey(Association)
class Meta:
db_table = 'Administrator'
I'm not sure I understand your question correctly. You can access the authenticated user (given you are using the Django Authentication system) by calling self.request.user.
You have to create a relation between Association and the user:
class Association(models.Model):
asoc_name = models.CharField(max_length=50, null=True, blank=True, unique=True)
# Option 1 - if one user can be a member of several associations
members = models.ManyToMany(User)
class Meta:
db_table = 'Association'
or a new model instance if a user can only be a member of one association:
# Option 2
class Membership(Model):
association = models.ForeignKey(Association)
user = models.ForeignKey(User, unique=True)
You get the Association using a direct lookup (or a reverse relation).
# option 1
if form.is_valid():
sender = Association.objects.filter(members=self.request.user).first()
# sender might be None
# option 2
if form.is_valid():
membership = Membership.objects.filter(user=self.request.user).first()
if membership:
sender = membership.association
https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/

Filter select field in ModelForm by currently logged in user

I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .