Finding an username using an id in django - python

I would like to use an id to search my database for the username that belongs to that id.
I have a url.py setup to give the id via an url variable then I pass it onto the views.py that passes it to the template
At the moment I have the following:
models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
pass
def __str__(self):
return self.email
docfile = models.FileField(upload_to='static/users/',)
views.py
def ProfileView(request, id):
return render(request, 'pages/profile.html', {"id":id})
urls.py
path('profile/<int:id>', views.ProfileView, name='Profile')
profile.html
<div class="mainusers">
<div class = "userLine">
<p>{{ id.username }}</p> <!-- I know this wouldn't work, It's just a place holder at the moment -->
<center><p></p><p class="mainfont"><u>{{ id.username }}</u><p></center>
<div class="circular--portrait">
<img id="ProfileBox" src="../static/users/{{ id.username }}.gif" onerror="this.onerror=null;this.src='static/users/default.gif';"/>
</div>
<center><p><br></br> Date Joined: {{id.date_joined}}</p></center>
{% if id.is_superuser %}
<center><p>Developer</p></center>
{% endif %}
<div class="wrapper">
<button class="logout" onclick="window.location.href='{% url 'logout' %}'">Logout</button>
<button class="logout" onclick="window.location.href='/invgen'">Generate Invite Code</button>
</div>

You need to fetch the User object for that id:
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
def profile_view(request, id):
user = get_object_or_404(User, pk=id)
return render(request, 'pages/profile.html', {'id':id, 'user': user})
We can then render it like:
<img id="ProfileBox" src="../static/users/{{ user.username }}.gif" onerror="this.onerror=null;this.src='static/users/default.gif';"/>
If you make use of static files, it is however probably better to use the {% static ... %} template tag, as is described in the documentation.
Note: according tot PEP 8, one uses lowercase characters and an underscore as separator for functions, so it is probably better to rename ProfileView to profile_view, as I did here.

You can use the request object to find the logged in user i.e. request.user

Related

Django Form is not updating the user database

I want to update User database using forms.When I trying to update it remains same the database and not update. So to perform this task ?
forms.py
from django import forms
from django.contrib.auth.models import User
class updateform(forms.ModelForm):
class Meta:
model=User
fields="__all__"
views.py
from django.contrib.auth.models import User
from .forms import updateform
#permission_required('is_superuser')#only superuser can update the data base
def upform(request,id):
emp=User.objects.get(id=id)
if request.method=='POST':
frm=updateform(request.POST,instance=emp)
if frm.is_valid():
frm.save()
return redirect('/')
else:
frm=updateform(instance=emp)
return render(request,'examp.html',{'frm':frm})
examp.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static '/examp.css' %}">
<style>
td,th{
border:1px solid;
text-align:center;
padding:10px;
}
</style>
</head>
<body>
{% include 'include/header.html' %}
<form action="/" method="POST">
{% csrf_token %}
{{ frm.as_p }}
<input type="submit" value="Submit">
</form>
</body>
</html>
How to update the database using this given form.
Why don't you use CBV generic views?
in yourapp/models.py:
from django.db import models
from django.urls import reverse
from django.contrib.auth import get_user_model
# const for get_absolute_url
#that's suffix will be using in your template names look at urls.py,
#if you need u should change it for smth here and in urls!
DETAIL_SUFFIX = '_detail'
class YourModel(models.Model):
name = models.CharField(default='new', max_length=6)
updated_by = models.ForeignKey(get_user_model(), on_delete=models.PROTECT,
related_name='get_upd_by_user')
def __str__(self):
return f'{self.name}'
def get_absolute_url(self):
return reverse(f'{self.__class__.__name__}{DETAIL_SUFFIX}', kwargs={"pk": self.pk})
You need to define the get_absolute_url method. Then reverse will works properly after you update.
in yourapp/views.py:
#views
from django.views.generic.edit import UpdateView
from django.views.generic import DetailView
# AAA
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import PermissionRequiredMixin
class ProjectSubnetDetailView(LoginRequiredMixin, DetailView):
model = YourModel
template_name = 'your_name_detail.html'
class YourNameUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
model = YourModel
template_name = 'your_name_edit.html'
fields = ('somefield', )
permission_required = ('yourapp.view_yourmodel','yourapp.change_yourmodel')
def form_valid(self, form): # Bind name of current user
form.instance.updated_by = self.request.user
return super().form_valid(form)
Instead of decorator #permission_required in CBV you can use PermissionRequiredMixin(I highly recommend reading about it in the official documentation). In short you must define only in this order:
(LoginRequiredMixin, PermissionRequiredMixin, UpdateView)
First - user must be Authenticated
Second - user must have a rights (or roles, that have a need rights)
Third - thats your generic view for do smth (in this example is update)
For second Attention You must specify in the view those rights that are checked before performing the update in strictly lowercase.
You can define rights in admin panel for some user or create a role and define some rights and add your user into that role. For example i create user and define him some rights for view and change table:
So if your model is called 'YourModel', you should specify 'action_yourmodel'
permission_required = ('yourapp.view_yourmodel','yourapp.change_yourmodel')
in yourapp/urls.py.
from django.urls import path
from .views import YourNameUpdateViewUpdateView, YourNameDetailView
urlpatterns = [
path('YourName/<int:pk>/edit/', YourNameUpdateView.as_view(), name='some_name_edit'),
path('YourName/<int:pk>/detail/', YourNameDetailView.as_view(), name='some_name_detail'),
]
in yourapp/templates/ you have to define 2 templates:
#your_name_detail.html
{% extends '_basetemplate.html' %}
{% block content %}
<div>
<p>{{ object.name }}</p>
</div>
<p>
Update |
</p>
{% endblock content %}
# your_name_edit.html
{% extends '_basetemplate.html' %}
{% block content %}
<h5>Updating {{ object.name }}</h5>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-sm btn-info ml-2" type="submit">Update</button>
</form>
{% endblock content %}

Django template and views functions

How can I pass a list of items into a template?
In my views:
from django.shortcuts import render, render_to_response
from django.http import HttpResponse
from django.template import loader
from django.views.decorators.csrf import csrf_exempt
from .models import Question
from .forms import usersData1, usersData2, usersData3
def start_pr(response):
name = ["Name","Phone Number","Email"]
form = usersData1()
return render_to_response(response, "start_pr/start.html", {"form":form}, {"name":name})
In my HTML:
{% block content %}
<form action="/start/" method="post">
<legend>
{%for items in form %}
{% for obj in name %}
<p> {{ obj }} </p>
{% endfor %}
<input type="text" name="name" maxlength="20" required="" id="id_name" placeholder="{{items.name}}">
<br>
{% endfor %}
next
</legend>
</form>
{% endblock %}
In my forms:
from Django import forms
class usersData1(forms.Form):
name= forms.CharField(label="name", max_length=20)
phoneNum= forms.IntegerField(label="phoneNum")
email= forms.EmailField(label="email", max_length=50)
The list is in my views as name. I have used {% for obj in name %}<p>{{obj}}</p>.
When I go to localhost:8000 it shows an HTML form as the out product. which is weird (like opening up google view page sources when right-clicked). I am also new to Django but know how to make views and link them along with most of the basics.
What I don't know is this {%%}; what is this symbol called, and where can I find documentation on this syntax?
What I am trying to achieve in this Django view is to have 3 boxes with names from the list name as the name for that box (pretty much an iteration).
If you want to pass two (or more) elements to the template, you do that in the same dictionary:
def start_pr(response):
name = ['Name', 'Phone Number', 'Email']
form = usersData1()
return render_to_response(
response,
'start_pr/start.html',
{'form': form, 'name':name}
)
However here it looks like you simply want to add placeholders. You can simply do that in the form:
from django import forms
class UsersData1(forms.Form):
name= forms.CharField(
label='Name',
max_length=20,
widget=forms.TextInput(attrs={'placeholder': 'Name'})
)
phoneNum = forms.IntegerField(
label='Phone Number',
widget=forms.NumberInput(attrs={'placeholder': 'Phone Number'})
)
email= forms.EmailField(
label='Email',
max_length=20,
widget=forms.TextInput(attrs={'placeholder': 'Email'})
)
This will avoid complicated logic in the template which is not the purpose of a template anyway. A template is used for rendering logic.

NoReverseMatch at /tinku/update

Reverse for 'update_student' with no arguments not found. 1 pattern(s) tried: ['(?P[-a-zA-Z0-9_]+)/update$']
it is showing error above please tell if anyone know about this how to resolve this
urls.py
path('',views.index,name="home"),
path('<slug:name>/update',views.student_update,name="update_student"),
path('delete/<slug:name>',views.student_delete,name="delete_student")
student_update.html
<div class=" row d-flex justify-content-center">
<div class="col-md-6 box-shadow">
<form action="{% url 'update_student' %}" method="POST" class="form">
{% csrf_token %}
{{updateform|crispy}}
<button class="btn btn-primary form-control">update</button>
</form>
</div>
views.py:-
def student_update(request,name):
instance=get_object_or_404(Student,name=name)
print(instance)
form=StudentForm(request.POST,instance=instance)
print(form)
if form.is_valid():
form.save()
return redirect('home')
return render(request,'webapp/student_update.html',{'updateform':form})
models.py
from django.db import models
from django.core.validators import MaxValueValidator,MinValueValidator
from django.contrib.auth.models import User
class Student(models.Model):
gender=(
('M','male'),
('F','female')
)
name=models.CharField(max_length=50)
age=models.PositiveIntegerField(validators=[MinValueValidator(18),MaxValueValidator(50)])
sex=models.CharField(max_length=1,choices=gender)
def __str__(self):
return self.name
forms.py
from django import forms
from django.core.validators import MaxValueValidator,MinValueValidator
from webapp.models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields=['name','age','sex']
You have {% url 'update_student' %} in your template (the form action), which is causing the error because the update_student pattern requires a name parameter.
So you either need to change it to {% url 'update_student' name=form.instance.name %} but since your form is posting to the same url as the one it's rendered on, it's easier to just remove the action attribute completely.

Wagtail: Add image to custom user model

I'm following the Wagtail documentation to customize the user model. I want to add an image to the user model.
Django version: 2.0.8,
Wagtail version: 2.1
Problem
After choosing an image with the image chooser field and clicking 'Save', this error shows up:
'No file was submitted. Check the encoding type on the form.'
Code
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
display_image = models.ForeignKey('wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+')
forms.py
from django import forms
from django.utils.translation import ugettext_lazy as _
from wagtail.users.forms import UserEditForm, UserCreationForm
from wagtail.images.widgets import AdminImageChooser
class CustomUserEditForm(UserEditForm):
display_image = forms.ImageField(
widget=AdminImageChooser(), label=_('Autorenbild'))
class CustomUserCreationForm(UserCreationForm):
display_image = forms.ImageField(
widget=AdminImageChooser(), label=_('Autorenbild'))}
edit.html
{% extends "wagtailusers/users/edit.html" %}
{% block extra_fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.display_image %}
{% endblock extra_fields %}
{% block extra_js %}
{{ block.super }}
{% include 'wagtailadmin/pages/_editor_js.html' %}
{% endblock extra_js %}
create.html similar
What I've tried so far
The idea to use the AdminImageChooser widget I found here. I had to adjust the forms by adding an forms.ImageField so that the User page displays without error.
Questions
Anyone know why the error occurs and how to fix it?
As stated in the above Google group thread, it seems as adding an image to the user model is 'a bit awkward'. What is a better approach to have an image connected to an user for repetitive usage in a site? A requirement is that the image can be easily changed in Wagtail admin.
Other problem with Wagtail version 2.2
In Settings > User in the admin interface, the window of the AdminImageChooser does not open.
Console shows following JS error:
Uncaught ReferenceError: createImageChooser is not defined
On Django 3.0.7 and wagtail wagtail 2.9, I could solve it like this:
models.py
class User(AbstractUser):
avatar = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
forms.py
It's important to use an ModelChoiceField and not an ImageField, so you are compliant with the AdminImageChooser widget.
from django import forms
from wagtail.images import get_image_model
from wagtail.images.widgets import AdminImageChooser
from wagtail.users.forms import UserCreationForm, UserEditForm
class CustomUserEditForm(UserEditForm):
avatar = forms.ModelChoiceField(
queryset=get_image_model().objects.all(), widget=AdminImageChooser(),
)
class CustomUserCreationForm(UserCreationForm):
avatar = forms.ModelChoiceField(
queryset=get_image_model().objects.all(), widget=AdminImageChooser(),
)
Templates
No need to load any Javascript manually. The widget do it for you.
Any-templates-dir/wagtailusers/users/create.html
{% extends "wagtailusers/users/create.html" %}
{% block extra_fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.avatar %}
{% endblock extra_fields %}
Any-templates-dir/wagtailusers/users/edit.html
{% extends "wagtailusers/users/edit.html" %}
{% block extra_fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.avatar %}
{% endblock extra_fields %}
Was using the last proposed solution in the same Google groups thread, also got the ReferenceError: createImageChooser is not defined js problem after updating from Wagtail 2.1 to 2.2
Here is how my research went:
Looks like this commit removed direct media js inclusion from _editor_js.html.
Okay, so the solution is to replicate the old behavour, and access the Media subclasses of widgets
First I tried adding the same removed lines to my own edit.html in {% block extra_js %}. Did not work.
Looks like some views return edit_handler, like here. User view does not.
What user view does provide, however, is form variable, in both create and edit views. Let's use it.
And the final solution for me was changing extra_js block in edit.html like so:
{% block extra_js %}
{{ block.super }}
{% include 'wagtailadmin/pages/_editor_js.html' %}
{{ form.media.js }}
{% endblock extra_js %}
models.py
class User(AbstractUser):
first_name = models.CharField(max_length=40, blank=False)
image = models.ImageField(blank=False, null=False, upload_to='image/', default='img/user.jpg')
def __str__(self):
return self.username
'''here you can add a model and their requirements too u can set path to remember one thing that image folder will create in media folder..so don't forget to add that folder there. like if you find it helpful'''
forms.py
class UserRegistrationForm(forms.ModelForm):
confirm_password2 = forms.CharField(widget=forms.PasswordInput,required=False)
class Meta:
model = User
fields = ['first_name','username','password','confirm_password2','image']
def clean(self):
cleaned_data = super(UserRegistrationForm, self).clean()
password = cleaned_data.get("password")
confirm_password2 = cleaned_data.get("confirm_password2")
if password != confirm_password2:
self.add_error('confirm_password2', "Password does not match")
return cleaned_data
'''def clean for password validation and i directly added fields which field i want in it'''
views.py
def Register_view(request):
form = UserRegistrationForm()
if request.method == 'POST':
form = UserRegistrationForm(request.POST, request.FILES)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data.get("password")
user.set_password(password)
user.save()
return redirect('login')
return render(request, 'register.html', {'form': form})
''' use request.files to add imagein your form'''
register.html
<form action="{% url 'register' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="body bg-gray">
<div class="form-group">
{{ form.as_p }}
</div>
</div>
<div class="footer">
<button type="submit" class="btn bg-olive btn-block">Sign me up</button>
I already have Account
</div>
</form>
''' user multipart to add image in it'''
For me the solution was to make sure you initialise the image field widget on the create and edit form classes with the AdminImageChooser
from wagtail.users.forms import UserEditForm
from wagtail.images.widgets import AdminImageChooser
class CustomUserEditForm(UserEditForm):
...
mugshot = AdminImageChooser()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['mugshot'].widget = AdminImageChooser()
You need to do this when you subclass the UserCreationForm too.
Django 3.2.6, Wagtail 2.14

Django form not passing is_valid() test

In my Django app in a Createview class it never enters the is_valid(): statement and I can not seem to find any errors:
models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.conf import settings
from .validators import validate_file_extension
import zipfile
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField(max_length=250)
date = models.DateTimeField(auto_now=True, auto_now_add=False)
album_image = models.FileField(validators=[validate_file_extension])
user = models.ForeignKey(User, default=1)
face = models.IntegerField(default=1)
def get_absolute_url(self):
return reverse('photos:detail',kwargs={'pk':self.pk})
def __str__(self):
return self.title
views.py
This is my view folder that contains a list view a detailed view and create view. Although the form doesnt pass the valid test, it still gets uploaded and is viewable by the user
from django.http import Http404
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.core.urlresolvers import reverse
from .forms import PostForm
from .models import Post
from django.contrib.auth.models import User
from django.template import loader
from django.views import generic
from django.views.generic.edit import CreateView
import cognitive_face as CF
import json
class IndexView(generic.ListView):
template_name='photos/post.html'
def get_queryset(self):
return Post.objects.filter(user=self.request.user)
class DetailView(generic.DetailView):
model = Post
template_name = 'photos/detail.html'
class PostCreate(generic.CreateView):
form = PostForm()
model = Post
if form.is_valid():
print('valid')
instance = form.save(commit=False)
username = form.cleaned_data['username']
album_image = form.cleaned_data['album_image']
instance.save()
if not form.is_valid():
print('not')
post_form.html
<html>
<body>
{% if request.user.is_authenticated%}
<h3>Hello {{request.user.username}}, please upload your image as either a .JPEG, .GIF or .PNG</h3>
{% endif %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
{% if request.user.is_authenticated %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
{{ form.errors }}
{{ form.non_field_errors }}
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
{% else %}
<p>You must be logged in to upload a file</p>
{% endif %}
</div>
</div>
</div>
</body>
</html>
urls.py
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from photos.models import Post
from . import views
app_name = 'photos'
urlpatterns = [
url(r'^$',views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$',views.DetailView.as_view(), name='detail'),
url(r'post/add/$', views.PostCreate.as_view(), name='post-add'),
]
You are writing function based view code inside a class based view, which is incorrect.
You shouldn't need to instantiate the form, or manually check whether it is valid. Just set form_class for the view, then override form_valid or form_invalid if you need to change the behaviour when the form is valid or invalid. Since you have {{ form.errors }} in your template, it should show any errors when you submit the form.
class PostCreate(generic.CreateView):
form_class = PostForm
model = Post
See the docs on form handling with class based views for more information. You might find it easier to write a function based view to begin with, since the flow of the code is easier to follow.

Categories