Differentiate between 'account types' in Django - python

Thanks in advance if you're reading this... I'm a High School student working on a web application using Django, to help students find internships, and facilitate parents posting internship offers -- a sort of marketplace if you will.
I'm trying to create a profile/account page for the users but I need a way to differentiate between whether the account logged in is a Student or Employer so that I can use views.py to generate a page appropriate to their account.
In models.py, I have two different profile types which can be associated with a user account (handled by django.contrib.auth), see below for reference.
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profilePic = models.ImageField(default='default.jpg', upload_to='profile_pics')
class Meta:
verbose_name = 'Student Profile'
def __str__(self):
return f"{self.user.username}'s Profile"
class Employer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profilePic = models.ImageField(default='default.jpg', upload_to='profile_pics')
company = models.CharField(max_length=100, default='Unspecified')
class Meta:
verbose_name = 'Employer/Parent Profile'
def __str__(self):
return f"{self.user.username}'s Profile"
In my views.py page, I'm trying to create a view for the account/profile that can detect whether the currently logged-in user's profile is linked to either the 'Student' or 'Parent' model and serve a page accordingly. I've tried a very rudimentary approach, as below, but unsurprisingly it's not working.
def account(request):
if user.student.username == True:
context = 'Account: Student'
return render(request, 'users/studentprofile.html', context)
elif user.employer.username == True:
context = 'Account: Employer'
return render(request, 'users/employer.html', context)
I was wondering if anyone had a suggestion as to how I can best accomplish this... apologies in advance is this approach is poorly structured or against the status-quo of Django Programming, I'm a complete beginner!
Thanks in advance all :)

As Morteza Afshari said, you should reorganize your models to include a boolean field.
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profilePic = models.ImageField(default='default.jpg', upload_to='profile_pics')
is_student = models.BooleanField(default=True)
class Meta:
verbose_name = 'Profile'
def __str__(self):
return f"{self.user.username}'s Profile"
This follows the DRY principle much better than your prior code because now we're not repeating fields like user, profilePic, etc.
Now we can rewrite your views.py like this:
def account(request):
if user.is_student:
context = 'Account: Student'
return render(request, 'users/studentprofile.html', context)
else:
context = 'Account: Employer'
return render(request, 'users/employer.html', context)

it would be better if you posted your exception/error alongside your code
but here's some hint:
context parameter passed to render function should be a dictionary not an string
context = {'Account: Student'}
and you should access to user with request.user not just user
if problems above didn't solve your problem
add these two lines of code at the beginning of your function:
print(request.user.student)
print(request.user.employer)

You can have an boolean field in user model like is_student and fill it during sign in. It can be null=True and null when user signed out.
If you have jwt token, you can store additional data in token to check where it comes from, or either store user current role in its cookie. Get us more data about your site structure for more related answers. (Data about authentication system, database structure or any more structural behaviors)

Related

Querying a data with Django ORM to return a specific data that belongs to a user

so I'm trying to build a Ledger App. When new users sign-ups, they create a new Business account that is linked to them (ForeignKey). Here is my model:
User = get_user_model()
class Business_Account(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
business_name = models.CharField(max_length=50)
Type_of_service = models.CharField(choices=SERVICE_CATEGORIES, max_length=50)
business_email_address = models.EmailField(max_length=254)
class Meta:
verbose_name = "Business_Account"
verbose_name_plural = "Business_Accounts"
def __str__(self):
return self.business_name
Now, I want to make a get request view that can query and returns a business account that belongs to a particular user. My current view just returns all the business accounts available in the database irrespective of which user is login. Here is my view:
class AddBusinessAcctView(APIView):
def get_object(self):
try:
return Business_Account.objects.all()
except:
raise status.HTTP_404_NOT_FOUND
def get(self,request):
queryset = self.get_object()
serializer = BusinessAcctSerializer(queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
Now, How can I query business accounts that belong to a particular user?. Thanks in advance
Normally, you'd have authentication and a logged-in user that you were trying to retrieve information for. Assuming you're going to do this, that user is available in the request object.
Business_Account.objects.get(user=request.user)
But in general, you can just do:
user = User.objects.get(username='john')
Business_Account.objects.get(user=request.user)
# or
Business_Account.objects.get(user_id=123456)
I finally got it. It is something similar to the above answer.
queryset = Business_Account.objects.filter(user=request.user)

Django admin filtering based on user profile

I have the following models in django:
class Manager(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
class Admin(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
In Djanog admin I would like to filter based on the company field of Manager OR Admin based on which is currently logged in.
I have the followin code for this:
def get_queryset(self, request):
qs = super(EmployeeAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
if hasattr(request.user, 'manager'):
return qs.filter(company=request.user.manager.company)
elif hasattr(request.user, 'admin'):
return qs.filter(company=request.user.admin.company)
It works nice, but I don't really like the way I have to allways check with hasattr() function which one is logged in. Also this is an error prone way, if I add another role for eg: Employer besides Manager and Ddmin and I forget to handle Employer...
Could you recommend a more neat solution for this?
Thank you!

User Follower model on Django. Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead

I am new to Django, Please forgive any silly mistakes in code or logic,
Intro: I am trying to create a user follower model in Django. Where users can follow and unfollow other users on the sites
Error: I have made the models for my follow/unfollow I have also made the views I am getting this error
AttributeError at /accounts/admin/follow/
Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead.
The obj.followers.add(user) is highlighted in the traceback as the origin of the error
Below are my models.py
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
city = models.CharField(max_length=100)
country = models.CharField(max_length=100)
def get_absolute_url(self):
return reverse('accounts:profile', kwargs={'username': self.user.username})
class Contact(models.Model):
user_from = models.ForeignKey(User, related_name='suppporter')
user_to = models.ForeignKey(User, related_name='leader')
def __str__(self):
return '{} follows {}'.format(self.user_from, self.user_to)
User.add_to_class('following',
models.ManyToManyField('self', through=Contact, related_name='followers', symmetrical=False))
I think the models.py may be good. The fault I believe is in my views.
Below is my view.py
class FollowToggle(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
username = self.kwargs.get('username')
print(username + " This is the user who will be followed") # This prints correct
profile = get_object_or_404(Profile, user__username=username)
print(profile) # This prints correct
obj = get_object_or_404(User, username=username)
print(obj) # This prints correct
url_ = profile.get_absolute_url()
print(url_) # This prints correct
user = self.request.user
print(user) # This prints correct
if user.is_authenticated():
if user in obj.followers.all(): # I know this is the source of the error.
obj.followers.remove(user)
else:
obj.followers.add(user)
return url_
Below are the Urls.py just in case
url(r'^(?P<username>[-\w]+)/follow/$', views.FollowToggle.as_view(), name='follow'),
You cannot use add and remove method for manytomany relation defined through third model. From the docs:
Unlike normal many-to-many fields, you can’t use add(), create(), or set() to create relationships
Instead you should use Contact manager:
if user.is_authenticated():
if user in obj.followers.all(): # I know this is the source of the error.
Contact.objects.filter(user_to=obj, user_from=user).delete()
else:
Contact.objects.create(user_to=obj, user_from=user)
In Django 2.2 you can use add, remove and set methods (Docs)
You can also use add(), create(), or set() to create relationships, as long as your specify through_defaults for any required fields

how to add post to django user model using foreignkey

i created a model
class ThisUser(models.Model):
created = models.DateTimeField(auto_now=True)
message = models.CharField(max_length=120)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.user
I want to store message specifically for the user who is authenticated.
right now this will give me all user who is available in my user model.
Please help
user = models.OneToOneField(User, on_delete=models.CASCADE)
Instead of foriegn key use one to one relation
Well you are suppose to take care of that at view level and not model level,
for example this is how I create a new Album:
#login_required
def make_album(request):
if request.method == 'POST':
form = AlbumCreationForm(request.POST)
if form.is_valid():
new_album = core_models.Album(name=form.cleaned_data['name'], description=form.cleaned_data['description'], user=request.user)`
You can use request.user.id to get user's id for further use.

How to save choices value in django ?

I am donig with a poll system for my class. I use model-form and create-view to serve the poll form. I use choices in in the field but I just find out that create-view only save the last value of the checkboxes and I want to save all the selected choices as a list maybe. I've tried to change the form_valid() method, but I just find out that I need to iterate all the fields to check wheather there are multipule choices. It's not flexible. And I can't figure out other solutions...
How can I meet this requirement? I am truly a newbie..
Thanks in advance.
Thank the friend below for replying in such a short interval after I raised my question. Here is my code.
models.py
CHOICES = (('m','Math'),('f','French'),('s','Science'),('l','literature'))
class Poll(models.Model):
[...]
subject = models.CharField(max_length = 5,choices = CHOICES, blank=True)
[...]`
forms.py
class PollForm(forms.ModelForm):
model = Poll
fields = [..., 'subject', ...]
widgets = {'subject':forms.CheckboxSelectMultiple}
views.py
class PollView(CreateView):
form_class = PollForm
template_name = 'poll.html'
Students can choose subjects they want.
It seems like you need to convert your model. If you could provide a sample of the structure that you are using it would be helpful. Still lets try solving your query. First you need identify that choices is nothing more than a many to many field. Saving it in the db should be a bit easier that way. Lets try taking an example with choices for a user:
class Choices(models.Model):
description = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.ForeignKey(User, blank=True, unique=True, verbose_name='profile_user')
choices = models.ManyToManyField(Choices)
def __unicode__(self):
return self.name
Now if you want to make a default form you could simply do something like:
class ProfileForm(forms.ModelForm):
Meta:
model = UserProfile
Now comes your main view. This can be editted and rendered to whatever your use case demands it to be:
if request.method=='POST':
form = ProfileForm(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
#Implement this as a pre-save so that you can add additional value
profile.save()
else:
form = ProfileForm()
Hope this helps.

Categories