I created a CustomUser as follows, however, I am not able to use the CustomUser functions in Views as I get the error message "get_first_name() missing 1 required positional argument: 'self'" when I call CustomUser.get_first_name().
I checked my settings.py and do import CustomUser, models as well as settings in the view file.
If you could help me here that would be awesome.
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name='email', unique=True)
first_name = models.CharField(verbose_name='first_name', max_length = 15)
last_name = models.CharField(verbose_name='last_name', max_length = 15)
organization = models.CharField(verbose_name="organization", max_length = 15, choices=ORGANIZATIONS)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True) # check this for login email purposes
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'organization']
objects = CustomUserManager()
def get_full_name(self):
'''
Returns the first_name plus the last_name, with a space in between.
'''
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns the short name for the user.
'''
return self.first_name
def __str__(self):
return self.email
def get_organization(self):
return self.organization
def get_first_name(self):
return self.first_name
def get_email(self):
return self.email
views.py
class Dashboard(LoginRequiredMixin, TemplateView):
template_name = "plot.html"
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(Dashboard, self).get_context_data(**kwargs)
context['plot'] = plots.plotsurvey()
return context
plots.py
def plotsurvey():
c = CustomUser()
name = c.get_first_name()
df = pd.read_csv(str(name) +'.csv') #
trace = go.Bar(
x = df['Y'],
y = df['Z'], name = 'N'
)
data = [trace]
layout = go.Layout(title="X", margin = dict(b = 150))
fig = go.Figure(data=data, layout=layout)
plot_div = plot(fig, output_type='div', include_plotlyjs=False)
#logger.info("Plotting number of points {}.".format(3))
return plot_div
You are using an instance method, as if it were a class method.
You need to change, this
def plotsurvey():
c = CustomUser()
name = CustomUser.get_first_name()
...
To this (use the instance)
def plotsurvey():
c = CustomUser()
name = c.get_first_name()
...
Note that you have another problem here. You are not actually getting any real user with c = CustomUser(). To get a user, you would need to do something like
CustomUser.objects.get(pk=user_id)
In that case, you finally get:
def plotsurvey(user_id):
c = CustomUser.objects.get(pk=user_id)
name = c.get_first_name()
...
EDIT
We can be more practical, using the view.
class Dashboard(LoginRequiredMixin, TemplateView):
template_name = "plot.html"
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(Dashboard, self).get_context_data(**kwargs)
user = self.request.user
context['plot'] = plots.plotsurvey(user.pk)
return context
You can use request object
request.user.get_first_name()
Related
I want to give users ten point each time they fill out one Survey , so i have this code above and now how to add the 10 point to self user after he fill out one
models.py :
class User(AbstractUser):
user_pic = models.ImageField(upload_to='img/',default="",null=True, blank=True)
coins = models.IntegerField(default=10)
def get_image(self):
if self.user_pic and hasattr(self.user_pic, 'url'):
return self.user_pic.url
else:
return '/path/to/default/image'
def give_coins(user, count):
user.coins = F('coins') + count
user.save(update_fields=('coins',))
user.refresh_from_db(fields=('coins',))
class Survey(models.Model):
name = models.CharField(max_length=200)
published_on = models.DateTimeField('Published DateTime')
def __str__(self):
return self.name
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.published_on <= now
was_published_recently.admin_order_field = 'published_on'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Participant(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
participation_datetime = models.DateTimeField('Participation DateTime')
def __str__(self):
return "Participant "+str(self.participation_datetime)
class Question(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
question_text = models.CharField(max_length=200)
created_on = models.DateTimeField('Creation DateTime')
def __str__(self):
return self.question_text
views.py :
#register.inclusion_tag('survey/survey_details.html', takes_context=True)
def survey_details(context, survey_id):
survey = Survey.objects.get(id=survey_id)
return {'survey': survey}
#require_http_methods(["POST"])
def submit_survey(request):
form_data = request.POST.copy()
form_items = list(form_data.items())
print("form_items", form_items)
form_items.pop(0) # the first element is the csrf token. Therefore omit it.
survey = None
for item in form_items:
# Here in 'choice/3', '3' is '<choice_id>'.
choice_str, choice_id = item
choice_id = int(choice_id.split('/')[1])
choice = Choice.objects.get(id=choice_id)
if survey is None:
survey = choice.question.survey
choice.votes = choice.votes + 1
choice.save()
if survey is not None:
participant = Participant(survey=survey, participation_datetime=timezone.now())
participant.save()
return redirect('/submit_success/')
so what i must to do if i want to add 10 point to user after he complete one survey
If submit_survey is a call that requires authentication the user will be present on the request request.user.
Add the coins by adding request.user.give_coins(count=10) to the submit_query method.
you have 2 way
work with event driven tools(maybe hard but principled)
set give_coin befor participant.save() on submit_survey
anyway I din't notice, coin is on your absUser model but your Participant has nothing to do with it or relations
I have this models:
Class Category(models.Model):
name = models.CharField(max_length=150, unique=True)
description = models.CharField(max_length=250)
def get_absolute_url(self):
return reverse('categories_url', args=[str(self.id)])
class Company(models.Model):
name = models.CharField(max_length=150, unique=True)
country = models.CharField(max_length=50)
class Motobike(models.Model):
name = models.CharField(max_length=150)
company = models.ForeignKey('Company', on_delete=models.CASCADE)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def get_absolute_url(self):
return reverse('details_url', args=[str(self.id)])
And views:
class CategoryView(DetailView):
model = Motobike
template_name = 'bikes_site/categories_detail.html'
pk_url_kwarg = 'pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
category = self.get_object()
context['motobikes'] = Motobike.objects.filter(category_id=category.pk)
return context
And test:
def test_category(setup):
client = Client()
category_id = Category.objects.get(name='Мотоциклы').id
response = client.get(f'/categories/{category_id}/')
assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8'))
assert len(response_data) == 2
assert response_data[1]['name'] == 'Ninja Turbo'
assert response_data[1]['vendor'] == 'Kawasaki'
assert response_data[1]['category'] == 'Мотоциклы'
assert response_data[1]['description'] == ''
response = client.get(f'/categories/25/')
assert response.status_code == 404
I need to present all thin in JSON, through JsonResponce, and what should almost go to the meaning of the dictonary, did i create them correctly?
You should do something like in your view:
from django.http import JsonResponse
class CategoryView(DetailView):
model = Motobike
template_name = 'bikes_site/categories_detail.html'
pk_url_kwarg = 'pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
category = self.get_object()
context['motobikes'] = Motobike.objects.filter(category_id=category.pk)
return JsonResponse(context, status=200) # or wahtever status is appropriate
Note: Haven't tested it, but that's what I use with GenericAPIView
I have a problem with a queryset in one view. My idea is show all users who are not registered in a program, I put here the models:
models.py
class UCAUser(AbstractUser):
dni_cif=models.CharField(
max_length=9,
blank=True,
verbose_name="DNI/CIF"
)
class InscripcionRealizada(models.Model):
formulario = models.ForeignKey(Formulario)
inscrito = models.ForeignKey(UCAUser,related_name="inscripciones_realizadas")
fecha_registro = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Inscripción realizada"
verbose_name_plural = "Inscripciones realizadas"
def __str__(self):
return "{} - {} - {}".format(self.formulario.programa, self.formulario.edicion, self.inscrito)
You can see UCAUser and InscripcionRealizada are connected by InscripcionRealizada.inscrito field.
view.py
class InscribirUsuariosListView(ListView):
template_name = "inscripciones/InscribirUsuariolist.html"
model = UCAUser
group_required = ['Administrador']
login_url = "auth-login"
def get_queryset(self):
qs = super(InscribirUsuariosListView, self).get_queryset()
return qs.filter(UCAUser.objects.filter(inscripciones_realizadas__formulario!=self.kwargs['formulario_id']))
def get_context_data(self, **kwargs):
context = super(InscribirUsuariosListView, self).get_context_data(**kwargs)
context['formulario_id'] = self.kwargs['formulario_id']
return context
When I try this, I get an error:
not enough values to unpack (expected 2, got 1)
Any idea?
I'm unable to figure out how to only call a queryset of items that belong to a specific User in the django forms.
dropoffs/models.py
class DropoffItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
dropoff = models.ForeignKey('Dropoff', null=True, blank=True)
product = models.ForeignKey(Product)
location = models.CharField(max_length=120, choices=LOCATION_CHOICES, default="Customer")
def __str__(self):
return str('%s' + " " + "(" + '%s' + ")") %(self.product.title, self.product.sku)
def sku(self):
return self.product.sku
def title(self):
return self.product.title
def dropoff_id(self):
return str(self.dropoff.id)
forms.py
class AddPickupItemForm(forms.ModelForm):
dropoffitem = forms.ModelChoiceField(queryset=DropoffItem.objects.none())
class Meta:
model = PickupItem
# fields = ["product", "quantity"]
fields = ['dropoffitem']
def __init__(self, user, *args, **kwargs):
# self.request = kwargs.pop("request")
the_user = kwargs.pop('user', None)
super(AddPickupItemForm, self).__init__(*args, **kwargs)
if the_user is not None:
self.fields["dropoffitem"].queryset = DropoffItem.objects.filter(user=the_user)
views.py
def add_item_to_pickup_order(request):
request.session.set_expiry(120000)
try:
user = request.user
the_id = request.session['pickup_id']
pickup = Pickup.objects.get(id=the_id)
except:
user = request.user
new_pickup_order = Pickup(user=user)
new_pickup_order.save()
request.session['pickup_id'] = new_pickup_order.id
the_id = new_pickup_order.id
pickup = Pickup.objects.get(id=the_id)
try:
dropoffitem = DropoffItem.objects.filter(user=user)
except DropoffItem.DoesNotExist:
pass
except:
pass
form = AddPickupItemForm(request.POST, user=request.user)
if request.method == "POST":
dropoffitem_id = int(request.POST['dropoffitem'])
pickup_item = PickupItem.objects.create(pickup=pickup, dropoffitem_id=dropoffitem_id)
pickup_item.save()
return HttpResponseRedirect('%s'%(reverse('add_item_to_pickup_order')))
context = {
"pickup": pickup,
"form": form,
}
return render(request, 'pickups/create_pickup_order.html', context)
With the modifications to init, I'm getting a TypeError of: init() got multiple values for keyword argument 'user'.
Could that be because of how I'm requesting a 'session'?
class AddPickupItemForm(ModelForm):
def __init__(self,*args,**kwargs)
the_user = kwargs.pop('user',None)
super(AddPickupItemForm, self).__init__(*args,**kwargs)
if the_user is not None:
self.fields['dropoffitem'].queryset = DropOffItem.objects.filter(user=the_user)
In other words, pass your user to the form when instantiating, if you need to.
I'm trying to make an editing page for the users to update an object data. However, form.is_valid() keeps failing, I have no idea why.
My model:
class Thread(models.Model):
title = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
body = models.TextField(max_length=10000)
USER_TYPES = (
('INI','Iniciante'),
('INT','Intermediário'),
('AVA','Avançado')
)
user_type = models.CharField(max_length=20, choices = USER_TYPES, default='INI')
category = models.ForeignKey(Category)
orcamento = models.IntegerField(default=0)
slug = models.SlugField(max_length=40, unique=True)
def get_absolute_url(self):
return "/%s/" % self.slug
def __str__(self):
return self.title
def save(self, **kwargs):
slug_str = "%s %s" % (self.category, self.title)
unique_slugify(self, slug_str)
super(Thread, self).save(**kwargs)
My view:
def edit_thread(request, thread_slug):
thread = Thread.objects.get(slug=thread_slug)
if request.method == 'POST':
form = EditThread(request.POST)
if form.is_valid():
thread.title = form.cleaned_data['title']
thread.orcamento = form.cleaned_data['orcamento']
thread.user_type = form.cleaned_data['experiencia']
thread.body = form.cleaned_data['pergunta']
thread.save()
return HttpResponseRedirect('/thread' + thread.get_absolute_url())
else:
data = {'title' : thread.title, 'experiencia':thread.user_type, 'orcamento' : thread.orcamento, 'pergunta': thread.body}
form = EditThread(initial=data)
return render(request, 'edit_thread.html', {
'form': form })
My form:
class EditThread(forms.ModelForm):
title = forms.CharField(label='Título', max_length=200, error_messages=my_default_errors)
orcamento = forms.IntegerField(label='Preço máximo', error_messages=my_default_errors)
experiencia = forms.ChoiceField(label='Você é um usuário...', choices=Thread.USER_TYPES, error_messages=my_default_errors)
pergunta = forms.CharField(label='Pergunta', widget=forms.Textarea, error_messages=my_default_errors)
class Meta:
model = Thread
def __init__(self, *args, **kwargs):
super(EditThread, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Div('title',
'experiencia',
PrependedAppendedText('orcamento', 'R$', ',00', active=True),
'pergunta',
FormActions(
Submit('save', 'Salvar alterações'),
)))
When accessing the page, the form gets pre-populated with the object's data as it should.
Your form should be inherited from the simple forms.Form instead of the forms.ModelForm:
class EditThread(forms.Form):
...
I would suggest you look at django's class based UpdateView. It can generate an update form for you or you could give it a custom ModelForm by overriding the form_class attribute on your view. When using a ModelForm, you also have to specify which model the form is for eg:
class EditThread(forms.ModelForm):
"field definitions ..."
class Meta:
model = Thread
fields = ['my_field_1', 'my_field_2']