Get the logged in user when there is request is not defined - django

I am having trouble to find a way to make it work;
I need to get the queryset with a list of the team created by the current logged in user.
My form look the following :
from django import forms
from django.contrib.auth.models import User
from registration.models import MyUser
from .models import Project, Team
from django.contrib.auth import get_user_model
User = get_user_model()
class EditSelectTeam(forms.Form):
team_choice = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=Team.objects.all().filter(team_hr_admin=request.User))
#team_id = forms.ChoiceField(queryset = Team.objects.filter(team_hr_admin= MyUser))
def team_select(self):
data = self.cleaned_data['team_choice']
return data
views.py:
def TeamSelect(request):
if request.method == "POST":
select_form = EditSelectTeam(request.POST)
print('sucess')
else:
select_form = EditSelectTeam(request)
return render(request,'link_project.html',
{'select_form':select_form })
I get the error that request is not define

you can pass the request using init method like:
class EditSelectTeam(forms.Form):
team_choice = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=None)
def __init__(self, request, *args, **kwargs):
super(EditSelecTeam, self).__init__(*args, **kwargs)
self.fields['team_choice'].queryset = Team.objects.all().filter(team_hr_admin=request.User))
def team_select(self):
data = self.cleaned_data['team_choice']
return data
Remember pass in your form the request like:
form = your_form(request)

Related

Accessing Middleware value for testing a Django DetailView

I am writing a test for a DetailView that queries get_object() by accessing a value set in a Middleware. This is for a Companies application and Company Model. Each user is in a Company.
To access the company throughout the project, I set the current user's Company.uuid on the request via a custom middleware.
Middleware
from django.utils.deprecation import MiddlewareMixin
class DynamicCompanyUUIDMiddleware(MiddlewareMixin):
""" Adds the current organization's UUID from the current user."""
def process_request(self, request):
try:
company_uuid = request.user.company_uuid
except:
company_uuid = None
request.company_uuid = company_uuid
That is used in the CompanyDetailView's get_object() method via a Mixin that I use for the other Company Views.
Mixin
class CompanyMixin(LoginRequiredMixin, SetHeadlineMixin):
model = Company
def get_object(self):
return get_object_or_404(
self.model,
uuid=self.request.user.company_uuid)
Test
The test that I'm trying to write is:
from django.test import RequestFactory
from django.urls import reverse, resolve
from test_plus.test import TestCase
from ..models import Company
from ..views import CompanyDetailView
class BaseCompanyTestCase(TestCase):
def setUp(self):
self.user = self.make_user()
self.object = Company.objects.create(owner=self.user, name="testcompany")
self.user.company_uuid = self.object.uuid
self.factory = RequestFactory()
class TestCompanyDetailView(BaseCompanyTestCase):
def setUp(self):
super(TestCompanyDetailView, self).setUp()
self.client.login(username="testuser", password="password")
self.view = CompanyDetailView()
self.view.object = self.object
request = self.factory.get(reverse('companies:detail'))
request.user = self.user
request.company_uuid = self.user.company_uuid
response = CompanyDetailView.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_get_headline(self):
self.assertEqual(
self.view.get_headline(),
'%s Members' % self.object.name
Result
This results in a 404 with the testuser's company not being found.
Walking through it:
I create the user
Create the company for this new testuser
Set the user.company_uuid
This should allow the mixin to access the company_uuid
Therefore return the user's company in the request
However I'm not returning the company as the 404 shows.
Question
Where am I going wrong on this? Thanks in advance for your help.
Answer
I was mixing Django's Client & RequestFactory. I have corrected the code above which is correct.
I was mixing Django's Client & RequestFactory. After stepping away, I figured it out below -
from django.test import RequestFactory
from django.urls import reverse, resolve
from test_plus.test import TestCase
from ..models import Company
from ..views import CompanyDetailView
class BaseCompanyTestCase(TestCase):
def setUp(self):
self.user = self.make_user()
self.object = Company.objects.create(owner=self.user, name="testcompany")
self.user.company_uuid = self.object.uuid
self.factory = RequestFactory()
class TestCompanyDetailView(BaseCompanyTestCase):
def setUp(self):
super(TestCompanyDetailView, self).setUp()
self.client.login(username="testuser", password="password")
self.view = CompanyDetailView()
self.view.object = self.object
request = self.factory.get(reverse('companies:detail'))
request.user = self.user
request.company_uuid = self.user.company_uuid
response = CompanyDetailView.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_get_headline(self):
self.assertEqual(
self.view.get_headline(),
'%s Members' % self.object.name

View with multiple forms not saving (missing 1 positional argument on form)

I have setup an override for Django-Registration-Redux to save on an additional model UserProfile below:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
tel_number = models.CharField(max_length=20, null = True)
This is setup with the following form:
class UserProfileRegistrationForm(RegistrationFormUniqueEmail):
tel_number = forms.CharField()
And regbackend.py:
from registration.backends.default.views import RegistrationView
from .forms import UserProfileRegistrationForm
from .models import UserProfile
class MyRegistrationView(RegistrationView):
form_class = UserProfileRegistrationForm
def register(self, request, form_class):
new_user = super(MyRegistrationView, self).register(request, form_class)
user_profile = UserProfile()
user_profile.user = new_user
user_profile.tel_number = form_class.cleaned_data['tel_number']
user_profile.save()
return user_profile
However, even though the view loads correctly and I can fill it out, I get the following error each time I save:
register() missing 1 required positional argument: 'form_class'
I assume this is something passing incorrectly?
I checked the code quickly here:
https://github.com/macropin/django-registration/blob/master/registration/backends/default/views.py
That Django-Registration-Redux seems to implement in RegistrationView, the register method like so:
def register(self, form):
#code
Try to remove request and it should work, sth like this.
def register(self, form_class):
new_user = super(MyRegistrationView, self).register(form_class)
#code

Django coverage report builder .xls export test

Im using coverage to test a view that exports a xls file using report builder code.
This is the view code :
from report_builder.models import Report
from report_utils.mixins import DataExportMixin, generate_filename
import re
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
class DownloadFileView(DataExportMixin, View):
#def dispatch(self, *args, **kwargs):
#return super(DownloadFileView, self).dispatch(*args, **kwargs)
def process_report(self, report_id, user_id,
file_type, to_response, queryset=None):
report = get_object_or_404(Report, pk=report_id)
user = User.objects.get(pk=user_id)
if not queryset:
queryset = report.get_query()
display_fields = report.get_good_display_fields()
#import pdb; pbb.set_trace()
objects_list, message = self.report_to_list(
queryset,
display_fields,
user,
preview=False,)
title = re.sub(r'\W+', '', report.name)[:30]
header = []
widths = []
for field in display_fields:
header.append(field.name)
widths.append(field.width)
if to_response:
return self.list_to_xlsx_response(
objects_list, title, header, widths)
def get(self, request, *args, **kwargs):
#report_id = 3
report_id= kwargs["report_id"]
file_type = 'xls'
user_id = 2
return self.process_report(
report_id, user_id, file_type, to_response=True)
And this is the test i wrote for it :
class test_reports_download(TestCase):
fixtures = ['test_data_cost_control_app.json']
def test_reports_select_get(self):
request = HttpRequest()
request.method = 'GET'
DownloadFileView.as_view()(request, report_id = 1, file_type = 'xls', user_id =2)
Coverage marks almost all view code as tested except for this 2 lines:
header.append(field.name)
widths.append(field.width)
Any idea why ?, i appreciate any help.
Thanks in advance

How to use handlers for django tastypie to make apis for UserProfile?

class UserProfile(models.Model):
"""
Extending the Django User.
"""
user = models.OneToOneField(User,unique=True)
image_id = models.CharField(max_length=50,blank=True)
is_email_validated = models.BolleanField(default = False)
followers_count = models.IntegerField(max_length=5,default=0,blank=True,null=True)
following_users = ModelListField()
follower_users = ModelListField()
def __unicode__(self):
return u"%s" % self.user.first_name
def full_name(self):
return u"%s" % self.user.first_name + '' + self.user.last_name
def email(self):
return self.user.email
def username(self):
return self.user.username
def books_count(self):
return len(self.user.get_profile().books)
def create_user_profile(sender,instance,created,**kwargs):
if created:
UserProfile.objects.create(user=instance)
action.send(type="create_user",actor=instance,target=instance)
post_save.connect(create_user_profile,sender=User)
Thus, how do I make an api out of it? Do I've to write handlers?(Quite confused how Django tastypie works in such situations.)
I could write handlers to return data for an api call like GET /users//following. But is this how it is done in tastypie? If yes, how do I connect the handler with the API?
Edit:
Something like this can be done in django-piston like this:
from piston.handler import BaseHandler
from piston.utils import rc
from app.apps.user.models import User, UserProfile
class UserHandler(BaseHandler):
model = User
def read(self, request, user_id=None, action=None):
"""
GET /users/
following - GET /users/<user_id>/following
followers - GET /users/<user_id>/followers
user profile - GET /users/<user_id>/
"""
if action =="following":
return self.following(request, user_id)
elif action == "followers":
return self.followers(request, user_id)
else:
return self.get_user_profile(request, user_id)
def get_user_profile(self, request, user_id):
"""
User Profile
GET /users/<user_id>/
"""
user = User.objects.get(pk=user_id)
user_session = request.user
user_session_following = user_session.get_profile().following_users
if user.id in user_session_following:
follow_status=True
else:
follow_status=False
return user_actions.get_user_profile(user, follow_status)
Put in your app/apps/user/api.py
from tastypie.resources import ModelResource
from django.contrib.auth.models import User
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
And in your urls.py
from django.conf.urls.defaults import *
from app.apps.user.api import UserResource
v1_api = Api(api_name='v1') #api_name will be 'v1' in http://localhost:8000/v1/?format=json
v1_api.register(UserProfileResource())
urlpatterns = patterns('',
(r'^api/', include(v1_api.urls)),
)
I don't mean to be crude here, but reading the documentation, specially the quickstart, would help.
Your api is now (in your devserver) exposed to
http://localhost:8000/api/v1/?format=json
Thats all. You don't have to write any code, for example to
- retrieve all users in json:
http://localhost:8000/api/v1/user/?format=json
- retrieve the entry in the user table with the key 1
http://localhost:8000/api/v1/user/1/?format=json
- retrieve the meta information about your UserResource
http://localhost:8000/api/v1/user/schema/?format=json
Hope this helps you!

adding extra field to django-registration using signals

I want to add a locale selection to the default django-registration. I tried to follow this tutorial from dmitko. The form shows up correctly but the additional data (locale) is not saved.
I defined a custom model:
class AnymalsProfile(models.Model):
user = models.ForeignKey(User, unique=True)
locale = models.CharField(max_length=2)
def __unicode__(self):
return u'%s %s' % (self.user, self.locale)
and the form:
from models import AnymalsProfile
from registration.forms import RegistrationFormTermsOfService
class UserRegistrationForm(RegistrationFormTermsOfService):
locale = forms.CharField(max_length=3, widget=forms.Select(choices=LOCALE_CHOICES),label='Language:')
The fields show up correctly, but the locale data (profile) is not saved. I assume that the regbackend.py is my problem:
from anysite.models import AnymalsProfile
def user_created(sender, user, request, **kwargs):
form = UserRegistrationForm(request.POST)
data = AnymalsProfile(user=user)
data.locale = form.cleaned_data["locale"]
data.save()
from registration.signals import user_registered
user_registered.connect(user_created)
* EDIT *
I tried moving into production - just for a test - and it raised some errors. I altered the code, but still the profile is not saved. Here is what I tried:
from anysite.models import AnymalsProfile
from anysite.forms import UserRegistrationForm
def user_created(sender, user, request, **kwargs):
form = UserRegistrationForm(request.POST)
if form.is_valid():
ProfileData = form.cleaned_data
profile = AnymalsProfile(
user = user.id,
locale = ProfileData["locale"]
)
profile.save()
from registration.signals import user_registered
user_registered.connect(user_created)
Do you have somewhere in your code import regbackend. That should be done in order to the following strings being executed.
from registration.signals import user_registered
user_registered.connect(user_created)
I my example I have import regbackend in urls.py. Do you have this line as well?
I don't know why, but it didn't like cleaned_data. It now works using the following:
def user_created(sender, user, request, **kwargs):
form = UserRegistrationForm(request.POST)
data = AnymalsProfile(user=user)
data.locale = form.data["locale"]
data.save()
Thanks #dmitko for the code and the support. keep it up!